1 # -*- Mode: Python; py-indent-offset: 4 -*-
3 # vim: tabstop=4 shiftwidth=4 expandtab
11 from compathelper import _unicode, _bytes
15 from gi.repository import GLib, GObject
18 from gi.repository import GdkPixbuf, Gdk, Gtk
20 PyGTKDeprecationWarning = Gtk.PyGTKDeprecationWarning
23 PyGTKDeprecationWarning = None
26 @contextlib.contextmanager
28 """Makes sure the widget is realized.
35 if isinstance(widget, Gtk.Window):
38 toplevel = widget.get_parent_window()
45 while Gtk.events_pending():
47 assert widget.get_realized()
54 while Gtk.events_pending():
58 @unittest.skipUnless(Gtk, 'Gtk not available')
59 class TestGtk(unittest.TestCase):
60 def test_container(self):
62 self.assertTrue(isinstance(box, Gtk.Box))
63 self.assertTrue(isinstance(box, Gtk.Container))
64 self.assertTrue(isinstance(box, Gtk.Widget))
70 self.assertTrue(label in box)
71 self.assertTrue(label2 in box)
72 self.assertEqual(len(box), 2)
75 self.assertEqual(l, [label, label2])
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)
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)
93 def test_actiongroup(self):
94 self.assertEqual(Gtk.ActionGroup, gi.overrides.Gtk.ActionGroup)
96 action_group = Gtk.ActionGroup(name='TestActionGroup')
97 callback_data = "callback data"
99 def test_action_callback_data(action, user_data):
100 self.assertEqual(user_data, callback_data)
102 def test_radio_action_callback_data(action, current, user_data):
103 self.assertEqual(user_data, callback_data)
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,
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)]
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)
134 def test_uimanager(self):
135 self.assertEqual(Gtk.UIManager, gi.overrides.Gtk.UIManager)
137 ui.add_ui_from_string("""<ui>
138 <menubar name="menubar1"></menubar>
142 menubar = ui.get_widget("/menubar1")
143 self.assertEqual(type(menubar), Gtk.MenuBar)
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])
153 def test_uimanager_nonascii(self):
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)
159 def test_window(self):
162 self.assertEqual(w.get_property('type'), Gtk.WindowType.TOPLEVEL)
164 # type works as keyword argument
165 w = Gtk.Window(type=Gtk.WindowType.POPUP)
166 self.assertEqual(w.get_property('type'), Gtk.WindowType.POPUP)
168 class TestWindow(Gtk.Window):
169 __gtype_name__ = "TestWindow"
172 builder = Gtk.Builder()
173 builder.add_from_string('''
175 <object class="GtkWindow" id="win">
176 <property name="type">popup</property>
178 <object class="TestWindow" id="testwin">
180 <object class="TestWindow" id="testpop">
181 <property name="type">popup</property>
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)
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)
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())
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),
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.*')
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.
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.*')
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.*')
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.*')
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.*')
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())
272 def test_about_dialog(self):
273 dialog = Gtk.AboutDialog()
274 self.assertTrue(isinstance(dialog, Gtk.Dialog))
275 self.assertTrue(isinstance(dialog, Gtk.Window))
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'))
281 def test_message_dialog(self):
282 dialog = Gtk.MessageDialog(title='message dialog test',
284 buttons=Gtk.ButtonsType.OK,
286 self.assertTrue(isinstance(dialog, Gtk.Dialog))
287 self.assertTrue(isinstance(dialog, Gtk.Window))
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)
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'))
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'))
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())
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)
313 dialog = Gtk.FileChooserDialog(title='file chooser dialog test',
314 action=Gtk.FileChooserAction.SAVE)
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())
321 action = dialog.get_property('action')
322 self.assertEqual(Gtk.FileChooserAction.SAVE, action)
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)
329 dialog = Gtk.FileChooserDialog(title='file chooser dialog test')
331 GLib.log_set_always_fatal(old_mask)
333 action = dialog.get_property('action')
334 self.assertEqual(Gtk.FileChooserAction.OPEN, action)
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())
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())
350 class TestClass(GObject.GObject):
351 __gtype_name__ = "GIOverrideTreeAPITest"
353 def __init__(self, tester, int_value, string_value):
354 super(TestGtk.TestClass, self).__init__()
356 self.int_value = int_value
357 self.string_value = string_value
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)
363 def test_buttons(self):
364 self.assertEqual(Gtk.Button, gi.overrides.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())
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())
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())
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):
395 klass = getattr(Gtk, element)
396 info = klass.__info__
397 except (NotImplementedError, AttributeError):
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"]
412 if kl.get_name() == name:
413 self.assertTrue(issubclass(klass, over,),
414 "%r does not inherit from override %r" % (klass, over,))
416 def test_editable(self):
417 self.assertEqual(Gtk.Editable, gi.overrides.Gtk.Editable)
419 # need to use Gtk.Entry because Editable is an interface
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)
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')
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)
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)
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)
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)
452 adjustment = Gtk.Adjustment(value=1, lower=0, upper=6)
453 self.adjustment_check(adjustment, value=1, lower=0, upper=6)
455 adjustment = Gtk.Adjustment()
456 self.adjustment_check(adjustment)
458 def test_table(self):
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)
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)
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)
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])
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())
489 def test_widget_drag_methods(self):
490 widget = Gtk.Button()
492 # here we are not checking functionality, only that the methods exist
493 # and except the right number of arguments
495 widget.drag_check_threshold(0, 0, 0, 0)
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()
509 widget.drag_highlight()
510 widget.drag_unhighlight()
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()
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'))
530 def test_drag_target_list(self):
531 mixed_target_list = [Gtk.TargetEntry.new('test0', 0, 0),
533 Gtk.TargetEntry.new('test2', 2, 2),
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)
543 _test_target_list(Gtk._construct_target_list(mixed_target_list))
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()
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()
554 treeview = Gtk.TreeView()
555 treeview.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK,
557 Gdk.DragAction.DEFAULT | Gdk.DragAction.MOVE)
559 treeview.enable_model_drag_dest(mixed_target_list,
560 Gdk.DragAction.DEFAULT | Gdk.DragAction.MOVE)
562 def test_scrollbar(self):
563 adjustment = Gtk.Adjustment()
565 hscrollbar = Gtk.HScrollbar()
566 vscrollbar = Gtk.VScrollbar()
567 self.assertNotEqual(hscrollbar.props.adjustment, adjustment)
568 self.assertNotEqual(vscrollbar.props.adjustment, adjustment)
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)
575 def test_iconview(self):
577 iconview = Gtk.IconView()
578 self.assertEqual(iconview.props.model, None)
580 model = Gtk.ListStore(str)
581 iconview = Gtk.IconView(model=model)
582 self.assertEqual(iconview.props.model, model)
584 def test_toolbutton(self):
586 button = Gtk.ToolButton()
587 self.assertEqual(button.props.stock_id, None)
589 button = Gtk.ToolButton(stock_id='gtk-new')
590 self.assertEqual(button.props.stock_id, 'gtk-new')
592 icon = Gtk.Image.new_from_stock(Gtk.STOCK_OPEN, Gtk.IconSize.SMALL_TOOLBAR)
594 button = Gtk.ToolButton(label='mylabel', icon_widget=icon)
595 self.assertEqual(button.props.label, 'mylabel')
596 self.assertEqual(button.props.icon_widget, icon)
598 def test_iconset(self):
600 pixbuf = GdkPixbuf.Pixbuf()
601 Gtk.IconSet.new_from_pixbuf(pixbuf)
603 def test_viewport(self):
604 vadjustment = Gtk.Adjustment()
605 hadjustment = Gtk.Adjustment()
607 viewport = Gtk.Viewport(hadjustment=hadjustment,
608 vadjustment=vadjustment)
610 self.assertEqual(viewport.props.vadjustment, vadjustment)
611 self.assertEqual(viewport.props.hadjustment, hadjustment)
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)
619 def test_gtk_main(self):
621 GLib.timeout_add(100, Gtk.main_quit)
624 # overridden function ignores its arguments
625 GLib.timeout_add(100, Gtk.main_quit, 'hello')
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)
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
642 self.assertNotEqual(value.get_int(), -42)
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)
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)
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')
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'}
670 Gtk.ScrolledWindow.__init__(self)
671 self._alloc_called = False
672 self._alloc_value = None
673 self._alloc_error = None
675 def do_size_allocate(self, alloc):
676 self._alloc_called = True
677 self._alloc_value = alloc
680 Gtk.ScrolledWindow.do_size_allocate(self, alloc)
681 except Exception as e:
682 self._alloc_error = e
684 win = WindowWithSizeAllocOverride()
685 rect = Gdk.Rectangle()
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)
697 @unittest.skipUnless(Gtk, 'Gtk not available')
698 class TestBuilder(unittest.TestCase):
699 class SignalTest(GObject.GObject):
700 __gtype_name__ = "GIOverrideSignalTest"
702 "test-signal": (GObject.SignalFlags.RUN_FIRST,
707 def test_extract_handler_and_args_object(self):
712 obj.foo = lambda: None
714 handler, args = Gtk.Builder._extract_handler_and_args(obj, 'foo')
715 self.assertEqual(handler, obj.foo)
716 self.assertEqual(len(args), 0)
718 def test_extract_handler_and_args_dict(self):
719 obj = {'foo': lambda: None}
721 handler, args = Gtk.Builder._extract_handler_and_args(obj, 'foo')
722 self.assertEqual(handler, obj['foo'])
723 self.assertEqual(len(args), 0)
725 def test_extract_handler_and_args_with_seq(self):
726 obj = {'foo': (lambda: None, 1, 2)}
728 handler, args = Gtk.Builder._extract_handler_and_args(obj, 'foo')
729 self.assertEqual(handler, obj['foo'][0])
730 self.assertSequenceEqual(args, [1, 2])
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')
738 def test_builder_with_handler_and_args(self):
739 builder = Gtk.Builder()
740 builder.add_from_string("""
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" />
751 def on_signal(*args):
752 args_collector.append(args)
754 builder.connect_signals({'on_signal1': (on_signal, 1, 2),
755 'on_signal2': on_signal})
757 objects = builder.get_objects()
758 self.assertEqual(len(objects), 1)
760 obj.emit('test-signal')
762 self.assertEqual(len(args_collector), 2)
763 self.assertSequenceEqual(args_collector[0], (obj, 1, 2))
764 self.assertSequenceEqual(args_collector[1], (obj, ))
766 def test_builder(self):
767 self.assertEqual(Gtk.Builder, gi.overrides.Gtk.Builder)
772 self.after_sentinel = 0
774 def on_signal_1(self, *args):
776 self.after_sentinel += 1
778 def on_signal_3(self, *args):
781 def on_signal_after(self, *args):
782 if self.after_sentinel == 1:
783 self.after_sentinel += 1
785 signal_checker = SignalCheck()
786 builder = Gtk.Builder()
788 # add object1 to the builder
789 builder.add_from_string("""
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" />
798 # only add object3 to the builder
799 builder.add_objects_from_string("""
801 <object class="GIOverrideSignalTest" id="object2">
802 <signal name="test-signal" handler="on_signal_2" />
804 <object class="GIOverrideSignalTest" id="object3">
805 <signal name="test-signal" handler="on_signal_3" />
807 <object class="GIOverrideSignalTest" id="object4">
808 <signal name="test-signal" handler="on_signal_4" />
814 builder.connect_signals(signal_checker)
816 # call their notify signals and check sentinel
817 objects = builder.get_objects()
818 self.assertEqual(len(objects), 2)
820 obj.emit('test-signal')
822 self.assertEqual(signal_checker.sentinel, 4)
823 self.assertEqual(signal_checker.after_sentinel, 2)
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)
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)
840 class TestPyObject(object):
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,
849 GObject.TYPE_PYOBJECT,
864 label = 'this is child #%d' % i
865 testobj = TestGtk.TestClass(self, i, label)
866 parent = tree_store.append(parent, (i,
883 parent = tree_store.append(parent)
885 label = 'this is child #%d' % i
886 testobj = TestGtk.TestClass(self, i, label)
887 tree_store.set(parent,
898 10, GObject.G_MAXULONG,
899 11, GObject.G_MININT64,
900 12, 0xffffffffffffffff,
904 parent = tree_store.append(parent)
906 label = 'this is child #%d' % i
907 testobj = TestGtk.TestClass(self, i, label)
908 tree_store.set(parent, {0: i,
918 10: GObject.G_MAXULONG,
919 11: GObject.G_MININT64,
920 12: 0xffffffffffffffff,
924 parent = tree_store.append(parent)
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),
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)
950 # walk the tree to see if the values were stored correctly
954 treeiter = tree_store.iter_children(parent)
956 i = tree_store.get_value(treeiter, 0)
957 s = tree_store.get_value(treeiter, 1)
958 obj = tree_store.get_value(treeiter, 2)
960 obj2 = tree_store.get_value(treeiter, 3)
961 self.assertEqual(obj, obj2)
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)
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))
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')
990 treeiter = tree_store.iter_children(parent)
992 self.assertEqual(i, 99)
994 def test_tree_store_signals(self):
995 tree_store = Gtk.TreeStore(int, bool)
997 def on_row_inserted(tree_store, tree_path, tree_iter, signal_list):
998 signal_list.append('row-inserted')
1000 def on_row_changed(tree_store, tree_path, tree_iter, signal_list):
1001 signal_list.append('row-changed')
1004 tree_store.connect('row-inserted', on_row_inserted, signals)
1005 tree_store.connect('row-changed', on_row_changed, signals)
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'])
1012 tree_store.append(None)
1013 self.assertEqual(signals, ['row-inserted'])
1016 tree_store.prepend(None, (0, False))
1017 self.assertEqual(signals, ['row-inserted'])
1020 tree_store.prepend(None)
1021 self.assertEqual(signals, ['row-inserted'])
1024 tree_store.insert(None, 1, (0, False))
1025 self.assertEqual(signals, ['row-inserted'])
1028 tree_store.insert(None, 1)
1029 self.assertEqual(signals, ['row-inserted'])
1031 def test_list_store(self):
1032 class TestPyObject(object):
1035 test_pyobj = TestPyObject()
1036 test_pydict = {1: 1, "2": 2, "3": "3"}
1037 test_pylist = [1, "2", "3"]
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,
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)
1065 label = 'this is row #0'
1066 list_store.prepend((0,
1068 TestGtk.TestClass(self, 0, label),
1075 # test automatic unicode->str conversion
1077 label = _unicode('this is row #94')
1078 treeiter = list_store.append((i,
1080 TestGtk.TestClass(self, i, label),
1087 # add sorted items out of order to test insert* apis
1088 # also test sending in None to not set a column
1090 label = 'this is row #97'
1091 treeiter = list_store.append((None,
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)
1106 # this should append
1108 label = 'this is row #99'
1109 list_store.insert(9999, (i,
1111 TestGtk.TestClass(self, i, label),
1119 label = 'this is row #96'
1120 list_store.insert_before(treeiter, (i,
1122 TestGtk.TestClass(self, i, label),
1130 label = 'this is row #98'
1131 list_store.insert_after(treeiter, (i,
1133 TestGtk.TestClass(self, i, label),
1141 label = 'this is row #95'
1142 list_store.insert(95, (i,
1144 TestGtk.TestClass(self, i, label),
1152 label = 'this is row #100'
1153 treeiter = list_store.append()
1154 list_store.set(treeiter,
1157 2, TestGtk.TestClass(self, i, label),
1164 label = 'this is row #101'
1165 treeiter = list_store.append()
1166 list_store.set(treeiter, {1: label,
1168 2: TestGtk.TestClass(self, i, label),
1175 label = 'this is row #102'
1176 treeiter = list_store.append()
1177 list_store.set(treeiter, (1, 0, 2, 3, 4, 5, 6, 7),
1180 TestGtk.TestClass(self, i, label),
1187 self.assertEqual(len(list_store), 103)
1189 # walk the list to see if the values were stored correctly
1191 treeiter = list_store.get_iter_first()
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)
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)
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))
1214 treeiter = list_store.iter_next(treeiter)
1218 self.assertEqual(i, 102)
1220 def test_list_store_sort(self):
1221 def comp1(model, row1, row2, user_data):
1225 # make "m" smaller than anything else
1226 if v1.startswith('m') and not v2.startswith('m'):
1228 if v2.startswith('m') and not v1.startswith('m'):
1230 return (v1 > v2) - (v1 < v2)
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'))
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']])
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']])
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']])
1251 def test_list_store_signals(self):
1252 list_store = Gtk.ListStore(int, bool)
1254 def on_row_inserted(list_store, tree_path, tree_iter, signal_list):
1255 signal_list.append('row-inserted')
1257 def on_row_changed(list_store, tree_path, tree_iter, signal_list):
1258 signal_list.append('row-changed')
1261 list_store.connect('row-inserted', on_row_inserted, signals)
1262 list_store.connect('row-changed', on_row_changed, signals)
1264 # adding rows with and without data should only call one signal
1265 list_store.append((0, False))
1266 self.assertEqual(signals, ['row-inserted'])
1270 self.assertEqual(signals, ['row-inserted'])
1273 list_store.prepend((0, False))
1274 self.assertEqual(signals, ['row-inserted'])
1277 list_store.prepend()
1278 self.assertEqual(signals, ['row-inserted'])
1281 list_store.insert(1, (0, False))
1282 self.assertEqual(signals, ['row-inserted'])
1285 list_store.insert(1)
1286 self.assertEqual(signals, ['row-inserted'])
1288 def test_tree_path(self):
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)
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)
1321 def test_tree_model(self):
1322 tree_store = Gtk.TreeStore(int, str)
1324 self.assertTrue(tree_store)
1325 self.assertEqual(len(tree_store), 0)
1326 self.assertEqual(tree_store.get_iter_first(), None)
1328 def get_by_index(row, col=None):
1330 return tree_store[row][col]
1332 return tree_store[row]
1334 self.assertRaises(TypeError, get_by_index, None)
1335 self.assertRaises(TypeError, get_by_index, "")
1336 self.assertRaises(TypeError, get_by_index, ())
1338 self.assertRaises(IndexError, get_by_index, "0")
1339 self.assertRaises(IndexError, get_by_index, 0)
1340 self.assertRaises(IndexError, get_by_index, (0,))
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,))
1346 self.assertRaises(ValueError, tree_store.get_iter_from_string, "0")
1348 for row in tree_store:
1349 self.fail("Should not be reached")
1351 class DerivedIntType(int):
1354 class DerivedStrType(str):
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)
1362 label = 'this is child #%d of node #%d' % (j, i)
1363 child = tree_store.append(parent, (j, label,))
1364 self.assertNotEqual(child, None)
1366 self.assertTrue(tree_store)
1367 self.assertEqual(len(tree_store), 100)
1369 self.assertEqual(tree_store.iter_previous(tree_store.get_iter(0)), None)
1371 for i, row in enumerate(tree_store):
1372 self.assertEqual(row.model, tree_store)
1373 self.assertEqual(row.parent, None)
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)
1379 self.assertEqual(tree_store[i][0], i)
1380 self.assertEqual(tree_store[i][1], "this is row #%d" % i)
1382 aiter = tree_store.get_iter(i)
1383 self.assertEqual(tree_store.get_path(aiter), row.path)
1385 aiter = tree_store.get_iter(str(i))
1386 self.assertEqual(tree_store.get_path(aiter), row.path)
1388 aiter = tree_store.get_iter((i,))
1389 self.assertEqual(tree_store.get_path(aiter), row.path)
1391 self.assertEqual(tree_store.iter_parent(aiter), row.parent)
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))
1399 self.assertEqual(next, None)
1401 self.assertEqual(tree_store.iter_n_children(row.iter), 20)
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)
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))
1416 self.assertRaises(IndexError, get_by_index, child, 2)
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))
1421 nth_child = tree_store.iter_nth_child(row.iter, j)
1422 self.assertEqual(childrow.path, tree_store.get_path(nth_child))
1424 childrow2 = tree_store["%d:%d" % (i, j)]
1425 self.assertEqual(childrow.path, childrow2.path)
1427 childrow2 = tree_store[(i, j,)]
1428 self.assertEqual(childrow.path, childrow2.path)
1430 child = tree_store.iter_next(child)
1432 self.assertEqual(childrow.next.path, tree_store.get_path(child))
1434 self.assertEqual(child, childrow.next)
1435 self.assertEqual(child, None)
1437 self.assertEqual(j, 19)
1439 self.assertEqual(i, 99)
1442 for i in range(-1, -100, -1):
1444 self.assertEqual(tree_store[i][0], i_real)
1447 for j in range(-1, -20, -1):
1449 path = (i_real, j_real,)
1451 self.assertEqual(tree_store[path][-2], j_real)
1453 label = 'this was child #%d of node #%d' % (j_real, i_real)
1454 self.assertEqual(tree_store[path][-1], label)
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)
1460 self.assertRaises(IndexError, get_by_index, path, -3)
1462 self.assertRaises(IndexError, get_by_index, -101)
1464 last_row = tree_store[99]
1465 self.assertNotEqual(last_row, None)
1467 for i, childrow in enumerate(last_row.iterchildren()):
1469 self.assertTrue(tree_store.remove(childrow.iter))
1471 self.assertFalse(tree_store.remove(childrow.iter))
1473 self.assertEqual(i, 19)
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")
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'))
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)
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)
1501 self.assertEqual(tm.get_iter_first(), None)
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])
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"])
1516 model[0] = (3, "three", -0.3)
1518 def test_tree_row_slice(self):
1519 model = Gtk.ListStore(int, str, float)
1520 model.append([1, "one", -0.1])
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])
1530 model[0][:] = (2, "two", -0.2)
1531 self.assertEqual([2, "two", -0.2], model[0][:])
1533 model[0][:2] = (3, "three")
1534 self.assertEqual([3, "three", -0.2], model[0][:])
1536 model[0][1:] = ("four", -0.4)
1537 self.assertEqual([3, "four", -0.4], model[0][:])
1539 model[0][1:-1] = ("five",)
1540 self.assertEqual([3, "five", -0.4], model[0][:])
1542 model[0][0:3:2] = (6, -0.6)
1543 self.assertEqual([6, "five", -0.6], model[0][:])
1546 model[0][5:] = ("doesn't", "matter",)
1548 self.assertRaises(ValueError, set_row1)
1551 model[0][:1] = (0, "zero", 0)
1553 self.assertRaises(ValueError, set_row2)
1556 model[0][:2] = ("0", 0)
1558 self.assertRaises(TypeError, set_row3)
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])
1568 def test_signal_emission_tree_path_coerce(self):
1569 class Model(GObject.Object, Gtk.TreeModel):
1575 def on_any_signal(model, path, *args):
1576 tree_paths.append(path.to_string())
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)
1583 model.row_changed('0', Gtk.TreeIter())
1584 self.assertEqual(tree_paths[-1], '0')
1586 model.row_deleted('1')
1587 self.assertEqual(tree_paths[-1], '1')
1589 model.row_has_child_toggled('2', Gtk.TreeIter())
1590 self.assertEqual(tree_paths[-1], '2')
1592 model.row_inserted('3', Gtk.TreeIter())
1593 self.assertEqual(tree_paths[-1], '3')
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])
1600 filtered = Gtk.TreeModelFilter(child_model=model)
1602 self.assertEqual(filtered[0][1], 'one')
1603 filtered[0][1] = 'ONE'
1604 self.assertEqual(filtered[0][1], 'ONE')
1606 def test_list_store_performance(self):
1607 model = Gtk.ListStore(int, str)
1610 start = time.clock()
1613 model.append([1, 'hello'])
1616 sys.stderr.write('[%.0f µs/append] ' % ((end - start) * 1000000 / iterations))
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)
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()
1633 with realized(view):
1634 view.set_cursor(store[1].path)
1635 view.set_cursor(str(store[1].path))
1637 view.get_cell_area(store[1].path)
1638 view.get_cell_area(str(store[1].path))
1640 def test_tree_view_column(self):
1641 cell = Gtk.CellRendererText()
1642 col = Gtk.TreeViewColumn(title='This is just a test',
1647 # Regression test for: https://bugzilla.gnome.org/show_bug.cgi?id=711173
1648 col.set_cell_data_func(cell, None, None)
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'])
1657 tree = Gtk.TreeView(model=model)
1658 cell1 = Gtk.CellRendererText()
1659 cell2 = Gtk.CellRendererText()
1660 cell3 = Gtk.CellRendererText()
1661 cell4 = Gtk.CellRendererText()
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)
1667 tree.insert_column_with_attributes(-1, 'Head4', cell4)
1669 with realized(tree):
1670 tree.set_cursor(model[0].path)
1671 while Gtk.events_pending():
1672 Gtk.main_iteration()
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')
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)
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])
1691 treeview = Gtk.TreeView()
1692 treeview.set_model(store)
1694 column = Gtk.TreeViewColumn()
1695 treeview.append_column(column)
1697 cell = Gtk.CellRendererText()
1698 column.pack_start(cell, expand=True)
1699 column.set_attributes(cell, text=1)
1701 with realized(treeview):
1702 self.assertTrue(cell.props.text in directors)
1704 def test_tree_selection(self):
1705 store = Gtk.ListStore(int, str)
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()
1713 sel.select_path(firstpath)
1714 (m, s) = sel.get_selected()
1715 self.assertEqual(m, store)
1716 self.assertEqual(store.get_path(s), firstpath)
1719 (m, s) = sel.get_selected()
1720 self.assertEqual(m, store)
1721 self.assertEqual(store.get_path(s), firstpath)
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)
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)
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')
1741 self.assertEqual(tag.props.name, 'title')
1742 self.assertEqual(tag.props.font, 'Sans 18')
1744 (start, end) = buffer.get_bounds()
1746 mark = buffer.create_mark(None, start)
1747 self.assertFalse(mark.get_left_gravity())
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')
1755 (start, end) = buffer.get_bounds()
1756 text = buffer.get_text(start, end, False)
1757 self.assertEqual(text, '')
1759 buffer.insert(end, 'HelloHello')
1760 buffer.insert(end, ' Bob')
1762 cursor_iter = end.copy()
1763 cursor_iter.backward_chars(9)
1764 buffer.place_cursor(cursor_iter)
1765 buffer.insert_at_cursor(' Jane ')
1767 (start, end) = buffer.get_bounds()
1768 text = buffer.get_text(start, end, False)
1769 self.assertEqual(text, 'Hello Jane Hello Bob')
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))
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))
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))
1790 self.assertRaises(ValueError, buffer.insert_with_tags_by_name,
1791 buffer.get_start_iter(), 'HelloHello', 'unknowntag')
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())
1810 def test_text_buffer_search(self):
1811 buffer = Gtk.TextBuffer()
1812 buffer.set_text('Hello World Hello GNOME')
1814 i = buffer.get_iter_at_offset(0)
1815 self.assertTrue(isinstance(i, Gtk.TextIter))
1817 self.assertEqual(i.forward_search('world', 0, None), None)
1819 (start, end) = i.forward_search('World', 0, None)
1820 self.assertEqual(start.get_offset(), 6)
1821 self.assertEqual(end.get_offset(), 11)
1823 (start, end) = i.forward_search('world',
1824 Gtk.TextSearchFlags.CASE_INSENSITIVE,
1826 self.assertEqual(start.get_offset(), 6)
1827 self.assertEqual(end.get_offset(), 11)
1830 @unittest.skipUnless(Gtk, 'Gtk not available')
1831 class TestContainer(unittest.TestCase):
1832 def test_child_set_property(self):
1834 child = Gtk.Button()
1835 box.pack_start(child, expand=False, fill=True, padding=0)
1837 box.child_set_property(child, 'padding', 42)
1839 value = GObject.Value(int)
1840 box.child_get_property(child, 'padding', value)
1841 self.assertEqual(value.get_int(), 42)
1843 def test_child_get_property_gvalue(self):
1845 child = Gtk.Button()
1846 box.pack_start(child, expand=False, fill=True, padding=42)
1848 value = GObject.Value(int)
1849 box.child_get_property(child, 'padding', value)
1850 self.assertEqual(value.get_int(), 42)
1852 def test_child_get_property_return_with_explicit_gvalue(self):
1854 child = Gtk.Button()
1855 box.pack_start(child, expand=False, fill=True, padding=42)
1857 value = GObject.Value(int)
1858 result = box.child_get_property(child, 'padding', value)
1859 self.assertEqual(result, 42)
1861 def test_child_get_property_return_with_implicit_gvalue(self):
1863 child = Gtk.Button()
1864 box.pack_start(child, expand=False, fill=True, padding=42)
1866 result = box.child_get_property(child, 'padding')
1867 self.assertEqual(result, 42)
1869 def test_child_get_property_error(self):
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')
1876 def test_child_get_and_set(self):
1878 child = Gtk.Button()
1879 box.pack_start(child, expand=True, fill=True, padding=42)
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)
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)