functions: revert the function init order to make pylint happy again. See #217
[pygobject.git] / tests / test_overrides_gtk.py
blob1e3655250c271b24fd5dec5e14d90731fae48562
1 # -*- Mode: Python; py-indent-offset: 4 -*-
2 # coding: UTF-8
3 # vim: tabstop=4 shiftwidth=4 expandtab
5 from __future__ import absolute_import
7 import contextlib
8 import unittest
9 import time
10 import sys
11 import gc
12 import warnings
14 from .helper import ignore_gi_deprecation_warnings, capture_glib_warnings
16 import gi.overrides
17 import gi.types
18 from gi.repository import GLib, GObject
20 try:
21 from gi.repository import Gtk, GdkPixbuf, Gdk
22 PyGTKDeprecationWarning = Gtk.PyGTKDeprecationWarning
23 Gtk_version = Gtk._version
24 except ImportError:
25 Gtk = None
26 Gtk_version = None
27 PyGTKDeprecationWarning = None
28 GdkPixbuf = None
29 Gdk = None
32 def gtkver():
33 if Gtk is None:
34 return (0, 0, 0)
35 return (Gtk.get_major_version(),
36 Gtk.get_minor_version(),
37 Gtk.get_micro_version())
40 @contextlib.contextmanager
41 def realized(widget):
42 """Makes sure the widget is realized.
44 view = Gtk.TreeView()
45 with realized(view):
46 do_something(view)
47 """
49 if isinstance(widget, Gtk.Window):
50 toplevel = widget
51 else:
52 toplevel = widget.get_parent_window()
54 if toplevel is None:
55 window = Gtk.Window()
56 window.add(widget)
58 widget.realize()
59 while Gtk.events_pending():
60 Gtk.main_iteration()
61 assert widget.get_realized()
62 yield widget
64 if toplevel is None:
65 window.remove(widget)
66 window.destroy()
68 while Gtk.events_pending():
69 Gtk.main_iteration()
72 @unittest.skipUnless(Gtk, 'Gtk not available')
73 def test_freeze_child_notif():
75 events = []
77 def on_notify(widget, spec):
78 events.append(spec.name)
80 b = Gtk.Box()
81 c = Gtk.Button()
82 c.connect("child-notify", on_notify)
83 c.freeze_child_notify()
84 b.pack_start(c, True, True, 0)
85 b.child_set_property(c, "expand", False)
86 b.child_set_property(c, "expand", True)
87 c.thaw_child_notify()
88 assert events.count("expand") == 1
89 del events[:]
91 with c.freeze_child_notify():
92 b.child_set_property(c, "expand", True)
93 b.child_set_property(c, "expand", False)
95 assert events.count("expand") == 1
98 @unittest.skipUnless(Gtk, 'Gtk not available')
99 def test_wrapper_toggle_refs():
100 class MyButton(Gtk.Button):
101 def __init__(self, height):
102 Gtk.Button.__init__(self)
103 self._height = height
105 def do_get_preferred_height(self):
106 return (self._height, self._height)
108 height = 142
109 w = Gtk.Window()
110 b = MyButton(height)
111 w.add(b)
112 b.show_all()
113 del b
114 gc.collect()
115 gc.collect()
116 assert w.get_preferred_size().minimum_size.height == height
119 @unittest.skipUnless(Gtk, 'Gtk not available')
120 @ignore_gi_deprecation_warnings
121 class TestGtk(unittest.TestCase):
122 def test_container(self):
123 box = Gtk.Box()
124 self.assertTrue(isinstance(box, Gtk.Box))
125 self.assertTrue(isinstance(box, Gtk.Container))
126 self.assertTrue(isinstance(box, Gtk.Widget))
127 self.assertTrue(box)
128 label = Gtk.Label()
129 label2 = Gtk.Label()
130 box.add(label)
131 box.add(label2)
132 self.assertTrue(label in box)
133 self.assertTrue(label2 in box)
134 self.assertEqual(len(box), 2)
135 self.assertTrue(box)
136 labels = [x for x in box]
137 self.assertEqual(labels, [label, label2])
139 @unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
140 def test_actions(self):
141 self.assertEqual(Gtk.Action, gi.overrides.Gtk.Action)
142 action = Gtk.Action(name="test", label="Test", tooltip="Test Action", stock_id=Gtk.STOCK_COPY)
143 self.assertEqual(action.get_name(), "test")
144 self.assertEqual(action.get_label(), "Test")
145 self.assertEqual(action.get_tooltip(), "Test Action")
146 self.assertEqual(action.get_stock_id(), Gtk.STOCK_COPY)
148 self.assertEqual(Gtk.RadioAction, gi.overrides.Gtk.RadioAction)
149 action = Gtk.RadioAction(name="test", label="Test", tooltip="Test Action", stock_id=Gtk.STOCK_COPY, value=1)
150 self.assertEqual(action.get_name(), "test")
151 self.assertEqual(action.get_label(), "Test")
152 self.assertEqual(action.get_tooltip(), "Test Action")
153 self.assertEqual(action.get_stock_id(), Gtk.STOCK_COPY)
154 self.assertEqual(action.get_current_value(), 1)
156 @unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
157 def test_actiongroup(self):
158 self.assertEqual(Gtk.ActionGroup, gi.overrides.Gtk.ActionGroup)
160 action_group = Gtk.ActionGroup(name='TestActionGroup')
161 callback_data = "callback data"
163 def test_action_callback_data(action, user_data):
164 self.assertEqual(user_data, callback_data)
166 def test_radio_action_callback_data(action, current, user_data):
167 self.assertEqual(user_data, callback_data)
169 action_group.add_actions([
170 ('test-action1', None, 'Test Action 1',
171 None, None, test_action_callback_data),
172 ('test-action2', Gtk.STOCK_COPY, 'Test Action 2',
173 None, None, test_action_callback_data)], callback_data)
174 action_group.add_toggle_actions([
175 ('test-toggle-action1', None, 'Test Toggle Action 1',
176 None, None, test_action_callback_data, False),
177 ('test-toggle-action2', Gtk.STOCK_COPY, 'Test Toggle Action 2',
178 None, None, test_action_callback_data, True)], callback_data)
179 action_group.add_radio_actions([
180 ('test-radio-action1', None, 'Test Radio Action 1'),
181 ('test-radio-action2', Gtk.STOCK_COPY, 'Test Radio Action 2')], 1,
182 test_radio_action_callback_data,
183 callback_data)
185 expected_results = [('test-action1', Gtk.Action),
186 ('test-action2', Gtk.Action),
187 ('test-toggle-action1', Gtk.ToggleAction),
188 ('test-toggle-action2', Gtk.ToggleAction),
189 ('test-radio-action1', Gtk.RadioAction),
190 ('test-radio-action2', Gtk.RadioAction)]
192 for action in action_group.list_actions():
193 a = (action.get_name(), type(action))
194 self.assertTrue(a in expected_results)
195 expected_results.remove(a)
196 action.activate()
198 @unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
199 def test_uimanager(self):
200 self.assertEqual(Gtk.UIManager, gi.overrides.Gtk.UIManager)
201 ui = Gtk.UIManager()
202 ui.add_ui_from_string("""<ui>
203 <menubar name="menubar1"></menubar>
204 </ui>
207 menubar = ui.get_widget("/menubar1")
208 self.assertEqual(type(menubar), Gtk.MenuBar)
210 ag = Gtk.ActionGroup(name="ag1")
211 ui.insert_action_group(ag)
212 ag2 = Gtk.ActionGroup(name="ag2")
213 ui.insert_action_group(ag2)
214 groups = ui.get_action_groups()
215 self.assertEqual(ag, groups[-2])
216 self.assertEqual(ag2, groups[-1])
218 @unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
219 def test_uimanager_nonascii(self):
220 ui = Gtk.UIManager()
221 ui.add_ui_from_string(b'<ui><menubar name="menub\xc3\xa6r1" /></ui>'.decode('UTF-8'))
222 mi = ui.get_widget("/menubær1")
223 self.assertEqual(type(mi), Gtk.MenuBar)
225 def test_window(self):
226 # standard Window
227 w = Gtk.Window()
228 self.assertEqual(w.get_property('type'), Gtk.WindowType.TOPLEVEL)
230 # type works as keyword argument
231 w = Gtk.Window(type=Gtk.WindowType.POPUP)
232 self.assertEqual(w.get_property('type'), Gtk.WindowType.POPUP)
234 class TestWindow(Gtk.Window):
235 __gtype_name__ = "TestWindow"
237 # works from builder
238 builder = Gtk.Builder()
239 builder.add_from_string('''
240 <interface>
241 <object class="GtkWindow" id="win">
242 <property name="type">popup</property>
243 </object>
244 <object class="TestWindow" id="testwin">
245 </object>
246 <object class="TestWindow" id="testpop">
247 <property name="type">popup</property>
248 </object>
249 </interface>''')
250 self.assertEqual(builder.get_object('win').get_property('type'),
251 Gtk.WindowType.POPUP)
252 self.assertEqual(builder.get_object('testwin').get_property('type'),
253 Gtk.WindowType.TOPLEVEL)
254 self.assertEqual(builder.get_object('testpop').get_property('type'),
255 Gtk.WindowType.POPUP)
257 def test_dialog_classes(self):
258 self.assertEqual(Gtk.Dialog, gi.overrides.Gtk.Dialog)
259 self.assertEqual(Gtk.FileChooserDialog, gi.overrides.Gtk.FileChooserDialog)
260 self.assertEqual(Gtk.RecentChooserDialog, gi.overrides.Gtk.RecentChooserDialog)
261 if Gtk_version != "4.0":
262 self.assertEqual(Gtk.ColorSelectionDialog, gi.overrides.Gtk.ColorSelectionDialog)
263 self.assertEqual(Gtk.FontSelectionDialog, gi.overrides.Gtk.FontSelectionDialog)
265 def test_dialog_base(self):
266 dialog = Gtk.Dialog(title='Foo', modal=True)
267 self.assertTrue(isinstance(dialog, Gtk.Dialog))
268 self.assertTrue(isinstance(dialog, Gtk.Window))
269 self.assertEqual('Foo', dialog.get_title())
270 self.assertTrue(dialog.get_modal())
272 def test_dialog_deprecations(self):
273 with warnings.catch_warnings(record=True) as warn:
274 warnings.simplefilter('always')
275 dialog = Gtk.Dialog(title='Foo', flags=Gtk.DialogFlags.MODAL)
276 self.assertTrue(dialog.get_modal())
277 self.assertEqual(len(warn), 1)
278 self.assertTrue(issubclass(warn[0].category, PyGTKDeprecationWarning))
279 self.assertRegexpMatches(str(warn[0].message),
280 '.*flags.*modal.*')
282 with warnings.catch_warnings(record=True) as warn:
283 warnings.simplefilter('always')
284 dialog = Gtk.Dialog(title='Foo', flags=Gtk.DialogFlags.DESTROY_WITH_PARENT)
285 self.assertTrue(dialog.get_destroy_with_parent())
286 self.assertEqual(len(warn), 1)
287 self.assertTrue(issubclass(warn[0].category, PyGTKDeprecationWarning))
288 self.assertRegexpMatches(str(warn[0].message),
289 '.*flags.*destroy_with_parent.*')
291 def test_dialog_deprecation_stacklevels(self):
292 # Test warning levels are setup to give the correct filename for
293 # deprecations in different classes in the inheritance hierarchy.
295 # Base class
296 self.assertEqual(Gtk.Dialog, gi.overrides.Gtk.Dialog)
297 with warnings.catch_warnings(record=True) as warn:
298 warnings.simplefilter('always')
299 Gtk.Dialog(flags=Gtk.DialogFlags.MODAL)
300 self.assertEqual(len(warn), 1)
301 self.assertRegexpMatches(warn[0].filename, '.*test_overrides_gtk.*')
303 # Validate overridden base with overridden sub-class.
304 self.assertEqual(Gtk.MessageDialog, gi.overrides.Gtk.MessageDialog)
305 with warnings.catch_warnings(record=True) as warn:
306 warnings.simplefilter('always')
307 Gtk.MessageDialog(flags=Gtk.DialogFlags.MODAL)
308 self.assertEqual(len(warn), 1)
309 self.assertRegexpMatches(warn[0].filename, '.*test_overrides_gtk.*')
311 # Validate overridden base with non-overridden sub-class.
312 self.assertEqual(Gtk.AboutDialog, gi.repository.Gtk.AboutDialog)
313 with warnings.catch_warnings(record=True) as warn:
314 warnings.simplefilter('always')
315 Gtk.AboutDialog(flags=Gtk.DialogFlags.MODAL)
316 self.assertEqual(len(warn), 1)
317 self.assertRegexpMatches(warn[0].filename, '.*test_overrides_gtk.*')
319 def test_dialog_add_buttons(self):
320 # The overloaded "buttons" keyword gives a warning when attempting
321 # to use it for adding buttons as was available in PyGTK.
322 with warnings.catch_warnings(record=True) as warn:
323 warnings.simplefilter('always')
324 dialog = Gtk.Dialog(title='Foo', modal=True,
325 buttons=('test-button1', 1))
326 self.assertEqual(len(warn), 1)
327 self.assertTrue(issubclass(warn[0].category, PyGTKDeprecationWarning))
328 self.assertRegexpMatches(str(warn[0].message),
329 '.*ButtonsType.*add_buttons.*')
331 dialog.add_buttons('test-button2', 2, 'gtk-close', Gtk.ResponseType.CLOSE)
332 button = dialog.get_widget_for_response(1)
333 self.assertEqual('test-button1', button.get_label())
334 button = dialog.get_widget_for_response(2)
335 self.assertEqual('test-button2', button.get_label())
336 button = dialog.get_widget_for_response(Gtk.ResponseType.CLOSE)
337 self.assertEqual('gtk-close', button.get_label())
339 def test_about_dialog(self):
340 dialog = Gtk.AboutDialog()
341 self.assertTrue(isinstance(dialog, Gtk.Dialog))
342 self.assertTrue(isinstance(dialog, Gtk.Window))
344 # AboutDialog is not sub-classed in overrides, make sure
345 # the mro still injects the base class "add_buttons" override.
346 self.assertTrue(hasattr(dialog, 'add_buttons'))
348 def test_message_dialog(self):
349 dialog = Gtk.MessageDialog(title='message dialog test',
350 modal=True,
351 buttons=Gtk.ButtonsType.OK,
352 text='dude!')
353 self.assertTrue(isinstance(dialog, Gtk.Dialog))
354 self.assertTrue(isinstance(dialog, Gtk.Window))
356 self.assertEqual('message dialog test', dialog.get_title())
357 self.assertTrue(dialog.get_modal())
358 text = dialog.get_property('text')
359 self.assertEqual('dude!', text)
361 dialog.format_secondary_text('2nd text')
362 self.assertEqual(dialog.get_property('secondary-text'), '2nd text')
363 self.assertFalse(dialog.get_property('secondary-use-markup'))
365 dialog.format_secondary_markup('2nd markup')
366 self.assertEqual(dialog.get_property('secondary-text'), '2nd markup')
367 self.assertTrue(dialog.get_property('secondary-use-markup'))
369 @unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
370 def test_color_selection_dialog(self):
371 dialog = Gtk.ColorSelectionDialog(title="color selection dialog test")
372 self.assertTrue(isinstance(dialog, Gtk.Dialog))
373 self.assertTrue(isinstance(dialog, Gtk.Window))
374 self.assertEqual('color selection dialog test', dialog.get_title())
376 def test_file_chooser_dialog(self):
377 # might cause a GVFS warning, do not break on this
378 with capture_glib_warnings(allow_warnings=True):
379 dialog = Gtk.FileChooserDialog(title='file chooser dialog test',
380 action=Gtk.FileChooserAction.SAVE)
382 self.assertTrue(isinstance(dialog, Gtk.Dialog))
383 self.assertTrue(isinstance(dialog, Gtk.Window))
384 self.assertEqual('file chooser dialog test', dialog.get_title())
386 action = dialog.get_property('action')
387 self.assertEqual(Gtk.FileChooserAction.SAVE, action)
389 def test_file_chooser_dialog_default_action(self):
390 # might cause a GVFS warning, do not break on this
391 with capture_glib_warnings(allow_warnings=True):
392 dialog = Gtk.FileChooserDialog(title='file chooser dialog test')
394 action = dialog.get_property('action')
395 self.assertEqual(Gtk.FileChooserAction.OPEN, action)
397 @unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
398 def test_font_selection_dialog(self):
399 dialog = Gtk.FontSelectionDialog(title="font selection dialog test")
400 self.assertTrue(isinstance(dialog, Gtk.Dialog))
401 self.assertTrue(isinstance(dialog, Gtk.Window))
402 self.assertEqual('font selection dialog test', dialog.get_title())
404 def test_recent_chooser_dialog(self):
405 test_manager = Gtk.RecentManager()
406 dialog = Gtk.RecentChooserDialog(title='recent chooser dialog test',
407 recent_manager=test_manager)
408 self.assertTrue(isinstance(dialog, Gtk.Dialog))
409 self.assertTrue(isinstance(dialog, Gtk.Window))
410 self.assertEqual('recent chooser dialog test', dialog.get_title())
412 class TestClass(GObject.GObject):
413 __gtype_name__ = "GIOverrideTreeAPITest"
415 def __init__(self, tester, int_value, string_value):
416 super(TestGtk.TestClass, self).__init__()
417 self.tester = tester
418 self.int_value = int_value
419 self.string_value = string_value
421 def check(self, int_value, string_value):
422 self.tester.assertEqual(int_value, self.int_value)
423 self.tester.assertEqual(string_value, self.string_value)
425 def test_buttons(self):
426 self.assertEqual(Gtk.Button, gi.overrides.Gtk.Button)
428 # test Gtk.Button
429 button = Gtk.Button()
430 self.assertTrue(isinstance(button, Gtk.Button))
431 self.assertTrue(isinstance(button, Gtk.Container))
432 self.assertTrue(isinstance(button, Gtk.Widget))
434 if Gtk_version != "4.0":
435 # Using stock items causes hard warning in devel versions of GTK+.
436 with capture_glib_warnings(allow_warnings=True):
437 button = Gtk.Button.new_from_stock(Gtk.STOCK_CLOSE)
439 self.assertEqual(Gtk.STOCK_CLOSE, button.get_label())
440 self.assertTrue(button.get_use_stock())
441 self.assertTrue(button.get_use_underline())
443 # test Gtk.Button use_stock
444 button = Gtk.Button(label=Gtk.STOCK_CLOSE, use_stock=True,
445 use_underline=True)
446 self.assertEqual(Gtk.STOCK_CLOSE, button.get_label())
447 self.assertTrue(button.get_use_stock())
448 self.assertTrue(button.get_use_underline())
450 # test Gtk.LinkButton
451 button = Gtk.LinkButton(uri='http://www.Gtk.org', label='Gtk')
452 self.assertTrue(isinstance(button, Gtk.Button))
453 self.assertTrue(isinstance(button, Gtk.Container))
454 self.assertTrue(isinstance(button, Gtk.Widget))
455 self.assertEqual('http://www.Gtk.org', button.get_uri())
456 self.assertEqual('Gtk', button.get_label())
458 def test_inheritance(self):
459 for name in gi.overrides.Gtk.__all__:
460 over = getattr(gi.overrides.Gtk, name)
461 for element in dir(Gtk):
462 try:
463 klass = getattr(Gtk, element)
464 info = klass.__info__
465 except (NotImplementedError, AttributeError):
466 continue
468 # Get all parent classes and interfaces klass inherits from
469 if isinstance(info, gi.types.ObjectInfo):
470 classes = list(info.get_interfaces())
471 parent = info.get_parent()
472 while parent.get_name() != "Object":
473 classes.append(parent)
474 parent = parent.get_parent()
475 classes = [kl for kl in classes if kl.get_namespace() == "Gtk"]
476 else:
477 continue
479 for kl in classes:
480 if kl.get_name() == name:
481 self.assertTrue(issubclass(klass, over,),
482 "%r does not inherit from override %r" % (klass, over,))
484 def test_editable(self):
485 self.assertEqual(Gtk.Editable, gi.overrides.Gtk.Editable)
487 # need to use Gtk.Entry because Editable is an interface
488 entry = Gtk.Entry()
489 pos = entry.insert_text('HeWorld', 0)
490 self.assertEqual(pos, 7)
491 pos = entry.insert_text('llo ', 2)
492 self.assertEqual(pos, 6)
493 text = entry.get_chars(0, 11)
494 self.assertEqual('Hello World', text)
496 def test_label(self):
497 label = Gtk.Label(label='Hello')
498 self.assertTrue(isinstance(label, Gtk.Widget))
499 self.assertEqual(label.get_text(), 'Hello')
501 def adjustment_check(self, adjustment, value=0.0, lower=0.0, upper=0.0,
502 step_increment=0.0, page_increment=0.0, page_size=0.0):
503 self.assertEqual(adjustment.get_value(), value)
504 self.assertEqual(adjustment.get_lower(), lower)
505 self.assertEqual(adjustment.get_upper(), upper)
506 self.assertEqual(adjustment.get_step_increment(), step_increment)
507 self.assertEqual(adjustment.get_page_increment(), page_increment)
508 self.assertEqual(adjustment.get_page_size(), page_size)
510 def test_adjustment(self):
511 adjustment = Gtk.Adjustment(value=1, lower=0, upper=6, step_increment=4, page_increment=5, page_size=3)
512 self.adjustment_check(adjustment, value=1, lower=0, upper=6, step_increment=4, page_increment=5, page_size=3)
514 adjustment = Gtk.Adjustment(value=1, lower=0, upper=6, step_increment=4, page_increment=5)
515 self.adjustment_check(adjustment, value=1, lower=0, upper=6, step_increment=4, page_increment=5)
517 adjustment = Gtk.Adjustment(value=1, lower=0, upper=6, step_increment=4)
518 self.adjustment_check(adjustment, value=1, lower=0, upper=6, step_increment=4)
520 adjustment = Gtk.Adjustment(value=1, lower=0, upper=6)
521 self.adjustment_check(adjustment, value=1, lower=0, upper=6)
523 adjustment = Gtk.Adjustment()
524 self.adjustment_check(adjustment)
526 adjustment = Gtk.Adjustment(1, -1, 3, 0, 0, 0)
527 self.adjustment_check(adjustment, value=1, lower=-1, upper=3)
529 adjustment = Gtk.Adjustment(1, -1, 3, 0, 0, 0, value=2)
530 self.adjustment_check(adjustment, value=2, lower=-1, upper=3)
532 @unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
533 def test_table(self):
534 table = Gtk.Table()
535 self.assertTrue(isinstance(table, Gtk.Table))
536 self.assertTrue(isinstance(table, Gtk.Container))
537 self.assertTrue(isinstance(table, Gtk.Widget))
538 self.assertEqual(table.get_size(), (1, 1))
539 self.assertEqual(table.get_homogeneous(), False)
541 table = Gtk.Table(n_rows=2, n_columns=3)
542 self.assertEqual(table.get_size(), (2, 3))
543 self.assertEqual(table.get_homogeneous(), False)
545 table = Gtk.Table(n_rows=2, n_columns=3, homogeneous=True)
546 self.assertEqual(table.get_size(), (2, 3))
547 self.assertEqual(table.get_homogeneous(), True)
549 label = Gtk.Label(label='Hello')
550 self.assertTrue(isinstance(label, Gtk.Widget))
551 table.attach(label, 0, 1, 0, 1)
552 self.assertEqual(label, table.get_children()[0])
554 def test_scrolledwindow(self):
555 sw = Gtk.ScrolledWindow()
556 self.assertTrue(isinstance(sw, Gtk.ScrolledWindow))
557 self.assertTrue(isinstance(sw, Gtk.Container))
558 self.assertTrue(isinstance(sw, Gtk.Widget))
559 sb = sw.get_hscrollbar()
560 self.assertEqual(sw.get_hadjustment(), sb.get_adjustment())
561 sb = sw.get_vscrollbar()
562 self.assertEqual(sw.get_vadjustment(), sb.get_adjustment())
564 def test_widget_drag_methods(self):
565 widget = Gtk.Button()
567 # here we are not checking functionality, only that the methods exist
568 # and except the right number of arguments
570 widget.drag_check_threshold(0, 0, 0, 0)
572 # drag_dest_ methods
573 widget.drag_dest_set(Gtk.DestDefaults.DROP, None, Gdk.DragAction.COPY)
574 widget.drag_dest_add_image_targets()
575 widget.drag_dest_add_text_targets()
576 widget.drag_dest_add_uri_targets()
577 widget.drag_dest_get_track_motion()
578 widget.drag_dest_set_track_motion(True)
579 widget.drag_dest_get_target_list()
580 widget.drag_dest_set_target_list(None)
581 widget.drag_dest_set_target_list(Gtk.TargetList.new([Gtk.TargetEntry.new('test', 0, 0)]))
582 widget.drag_dest_unset()
584 widget.drag_highlight()
585 widget.drag_unhighlight()
587 # drag_source_ methods
588 widget.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, None, Gdk.DragAction.MOVE)
589 widget.drag_source_add_image_targets()
590 widget.drag_source_add_text_targets()
591 widget.drag_source_add_uri_targets()
592 widget.drag_source_set_icon_name("_About")
593 widget.drag_source_set_icon_pixbuf(GdkPixbuf.Pixbuf())
594 if Gtk_version != "4.0":
595 widget.drag_source_set_icon_stock(Gtk.STOCK_ABOUT)
596 widget.drag_source_get_target_list()
597 widget.drag_source_set_target_list(None)
598 widget.drag_source_set_target_list(Gtk.TargetList.new([Gtk.TargetEntry.new('test', 0, 0)]))
599 widget.drag_source_unset()
601 # these methods cannot be called because they require a valid drag on
602 # a real GdkWindow. So we only check that they exist and are callable.
603 if Gtk_version != "4.0":
604 self.assertTrue(hasattr(widget, 'drag_dest_set_proxy'))
605 self.assertTrue(hasattr(widget, 'drag_get_data'))
607 @unittest.skipIf(sys.platform == "darwin", "crashes")
608 def test_drag_target_list(self):
609 mixed_target_list = [Gtk.TargetEntry.new('test0', 0, 0),
610 ('test1', 1, 1),
611 Gtk.TargetEntry.new('test2', 2, 2),
612 ('test3', 3, 3)]
614 def _test_target_list(targets):
615 for i, target in enumerate(targets):
616 self.assertTrue(isinstance(target, Gtk.TargetEntry))
617 self.assertEqual(target.target, 'test' + str(i))
618 self.assertEqual(target.flags, i)
619 self.assertEqual(target.info, i)
621 _test_target_list(Gtk._construct_target_list(mixed_target_list))
623 widget = Gtk.Button()
624 widget.drag_dest_set(Gtk.DestDefaults.DROP, None, Gdk.DragAction.COPY)
625 widget.drag_dest_set_target_list(mixed_target_list)
626 widget.drag_dest_get_target_list()
628 widget.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, None, Gdk.DragAction.MOVE)
629 widget.drag_source_set_target_list(mixed_target_list)
630 widget.drag_source_get_target_list()
632 treeview = Gtk.TreeView()
633 treeview.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK,
634 mixed_target_list,
635 Gdk.DragAction.DEFAULT | Gdk.DragAction.MOVE)
637 treeview.enable_model_drag_dest(mixed_target_list,
638 Gdk.DragAction.DEFAULT | Gdk.DragAction.MOVE)
640 @unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
641 def test_scrollbar(self):
642 adjustment = Gtk.Adjustment()
644 hscrollbar = Gtk.HScrollbar()
645 vscrollbar = Gtk.VScrollbar()
646 self.assertNotEqual(hscrollbar.props.adjustment, adjustment)
647 self.assertNotEqual(vscrollbar.props.adjustment, adjustment)
649 hscrollbar = Gtk.HScrollbar(adjustment=adjustment)
650 vscrollbar = Gtk.VScrollbar(adjustment=adjustment)
651 self.assertEqual(hscrollbar.props.adjustment, adjustment)
652 self.assertEqual(vscrollbar.props.adjustment, adjustment)
654 def test_iconview(self):
655 # PyGTK compat
656 iconview = Gtk.IconView()
657 self.assertEqual(iconview.props.model, None)
659 model = Gtk.ListStore(str)
660 iconview = Gtk.IconView(model=model)
661 self.assertEqual(iconview.props.model, model)
663 @unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
664 def test_toolbutton(self):
665 # PyGTK compat
667 # Using stock items causes hard warning in devel versions of GTK+.
668 with capture_glib_warnings(allow_warnings=True):
669 button = Gtk.ToolButton()
670 self.assertEqual(button.props.stock_id, None)
672 button = Gtk.ToolButton(stock_id='gtk-new')
673 self.assertEqual(button.props.stock_id, 'gtk-new')
675 icon = Gtk.Image.new_from_stock(Gtk.STOCK_OPEN, Gtk.IconSize.SMALL_TOOLBAR)
676 button = Gtk.ToolButton(label='mylabel', icon_widget=icon)
677 self.assertEqual(button.props.label, 'mylabel')
678 self.assertEqual(button.props.icon_widget, icon)
680 def test_toolbutton_gtk4(self):
681 icon = Gtk.Image.new()
682 button = Gtk.ToolButton(label='mylabel', icon_widget=icon)
683 self.assertEqual(button.props.label, 'mylabel')
684 self.assertEqual(button.props.icon_widget, icon)
686 @unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
687 def test_iconset(self):
688 Gtk.IconSet()
689 pixbuf = GdkPixbuf.Pixbuf()
690 Gtk.IconSet.new_from_pixbuf(pixbuf)
692 def test_viewport(self):
693 vadjustment = Gtk.Adjustment()
694 hadjustment = Gtk.Adjustment()
696 viewport = Gtk.Viewport(hadjustment=hadjustment,
697 vadjustment=vadjustment)
699 self.assertEqual(viewport.props.vadjustment, vadjustment)
700 self.assertEqual(viewport.props.hadjustment, hadjustment)
702 @unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
703 def test_stock_lookup(self):
704 stock_item = Gtk.stock_lookup('gtk-ok')
705 self.assertEqual(type(stock_item), Gtk.StockItem)
706 self.assertEqual(stock_item.stock_id, 'gtk-ok')
707 self.assertEqual(Gtk.stock_lookup('nosuchthing'), None)
709 def test_gtk_main(self):
710 # with no arguments
711 GLib.idle_add(Gtk.main_quit)
712 Gtk.main()
714 # overridden function ignores its arguments
715 GLib.idle_add(Gtk.main_quit, 'hello')
716 Gtk.main()
718 @unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
719 def test_widget_render_icon(self):
720 button = Gtk.Button(label='OK')
721 pixbuf = button.render_icon(Gtk.STOCK_OK, Gtk.IconSize.BUTTON)
722 self.assertTrue(pixbuf is not None)
725 @unittest.skipUnless(Gtk, 'Gtk not available')
726 @unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
727 class TestWidget(unittest.TestCase):
728 def test_style_get_property_gvalue(self):
729 button = Gtk.Button()
730 value = GObject.Value(int, -42)
731 button.style_get_property('focus-padding', value)
732 # Test only that the style property changed since we can't actuall
733 # set it.
734 self.assertNotEqual(value.get_int(), -42)
736 def test_style_get_property_return_with_explicit_gvalue(self):
737 button = Gtk.Button()
738 value = GObject.Value(int, -42)
739 result = button.style_get_property('focus-padding', value)
740 self.assertIsInstance(result, int)
741 self.assertNotEqual(result, -42)
743 def test_style_get_property_return_with_implicit_gvalue(self):
744 button = Gtk.Button()
745 result = button.style_get_property('focus-padding')
746 self.assertIsInstance(result, int)
747 self.assertNotEqual(result, -42)
749 def test_style_get_property_error(self):
750 button = Gtk.Button()
751 with self.assertRaises(ValueError):
752 button.style_get_property('not-a-valid-style-property')
755 @unittest.skipIf(sys.platform == "darwin", "hangs")
756 @unittest.skipUnless(Gtk, 'Gtk not available')
757 class TestSignals(unittest.TestCase):
758 def test_class_closure_override_with_aliased_type(self):
759 class WindowWithSizeAllocOverride(Gtk.ScrolledWindow):
760 __gsignals__ = {'size-allocate': 'override'}
762 def __init__(self):
763 Gtk.ScrolledWindow.__init__(self)
764 self._alloc_called = False
765 self._alloc_value = None
766 self._alloc_error = None
768 def do_size_allocate(self, alloc):
769 self._alloc_called = True
770 self._alloc_value = alloc
772 try:
773 Gtk.ScrolledWindow.do_size_allocate(self, alloc)
774 except Exception as e:
775 self._alloc_error = e
777 win = WindowWithSizeAllocOverride()
778 rect = Gdk.Rectangle()
779 rect.width = 100
780 rect.height = 100
782 with realized(win):
783 win.show()
784 win.get_preferred_size()
785 win.size_allocate(rect)
786 self.assertTrue(win._alloc_called)
787 self.assertIsInstance(win._alloc_value, Gdk.Rectangle)
788 self.assertTrue(win._alloc_error is None, win._alloc_error)
790 @unittest.expectedFailure # https://bugzilla.gnome.org/show_bug.cgi?id=735693
791 def test_overlay_child_position(self):
792 def get_child_position(overlay, widget, rect, user_data=None):
793 rect.x = 1
794 rect.y = 2
795 rect.width = 3
796 rect.height = 4
797 return True
799 overlay = Gtk.Overlay()
800 overlay.connect('get-child-position', get_child_position)
802 rect = Gdk.Rectangle()
803 rect.x = -1
804 rect.y = -1
805 rect.width = -1
806 rect.height = -1
808 overlay.emit('get-child-position', None, rect)
809 self.assertEqual(rect.x, 1)
810 self.assertEqual(rect.y, 2)
811 self.assertEqual(rect.width, 3)
812 self.assertEqual(rect.height, 4)
815 @unittest.skipUnless(Gtk, 'Gtk not available')
816 class TestBuilder(unittest.TestCase):
817 class SignalTest(GObject.GObject):
818 __gtype_name__ = "GIOverrideSignalTest"
819 __gsignals__ = {
820 "test-signal": (GObject.SignalFlags.RUN_FIRST,
821 None,
822 []),
825 def test_extract_handler_and_args_object(self):
826 class Obj():
827 pass
829 obj = Obj()
830 obj.foo = lambda: None
832 handler, args = Gtk._extract_handler_and_args(obj, 'foo')
833 self.assertEqual(handler, obj.foo)
834 self.assertEqual(len(args), 0)
836 def test_extract_handler_and_args_dict(self):
837 obj = {'foo': lambda: None}
839 handler, args = Gtk._extract_handler_and_args(obj, 'foo')
840 self.assertEqual(handler, obj['foo'])
841 self.assertEqual(len(args), 0)
843 def test_extract_handler_and_args_with_seq(self):
844 obj = {'foo': (lambda: None, 1, 2)}
846 handler, args = Gtk._extract_handler_and_args(obj, 'foo')
847 self.assertEqual(handler, obj['foo'][0])
848 self.assertSequenceEqual(args, [1, 2])
850 def test_extract_handler_and_args_no_handler_error(self):
851 obj = dict(foo=lambda: None)
852 self.assertRaises(AttributeError,
853 Gtk._extract_handler_and_args,
854 obj, 'not_a_handler')
856 def test_builder_with_handler_and_args(self):
857 builder = Gtk.Builder()
858 builder.add_from_string("""
859 <interface>
860 <object class="GIOverrideSignalTest" id="object_sig_test">
861 <signal name="test-signal" handler="on_signal1" />
862 <signal name="test-signal" handler="on_signal2" after="yes" />
863 </object>
864 </interface>
865 """)
867 args_collector = []
869 def on_signal(*args):
870 args_collector.append(args)
872 builder.connect_signals({'on_signal1': (on_signal, 1, 2),
873 'on_signal2': on_signal})
875 objects = builder.get_objects()
876 self.assertEqual(len(objects), 1)
877 obj, = objects
878 obj.emit('test-signal')
880 self.assertEqual(len(args_collector), 2)
881 self.assertSequenceEqual(args_collector[0], (obj, 1, 2))
882 self.assertSequenceEqual(args_collector[1], (obj, ))
884 def test_builder(self):
885 self.assertEqual(Gtk.Builder, gi.overrides.Gtk.Builder)
887 class SignalCheck:
888 def __init__(self):
889 self.sentinel = 0
890 self.after_sentinel = 0
892 def on_signal_1(self, *args):
893 self.sentinel += 1
894 self.after_sentinel += 1
896 def on_signal_3(self, *args):
897 self.sentinel += 3
899 def on_signal_after(self, *args):
900 if self.after_sentinel == 1:
901 self.after_sentinel += 1
903 signal_checker = SignalCheck()
904 builder = Gtk.Builder()
906 # add object1 to the builder
907 builder.add_from_string("""
908 <interface>
909 <object class="GIOverrideSignalTest" id="object1">
910 <signal name="test-signal" after="yes" handler="on_signal_after" />
911 <signal name="test-signal" handler="on_signal_1" />
912 </object>
913 </interface>
914 """)
916 # only add object3 to the builder
917 builder.add_objects_from_string("""
918 <interface>
919 <object class="GIOverrideSignalTest" id="object2">
920 <signal name="test-signal" handler="on_signal_2" />
921 </object>
922 <object class="GIOverrideSignalTest" id="object3">
923 <signal name="test-signal" handler="on_signal_3" />
924 </object>
925 <object class="GIOverrideSignalTest" id="object4">
926 <signal name="test-signal" handler="on_signal_4" />
927 </object>
928 </interface>
929 """, ['object3'])
931 # hook up signals
932 builder.connect_signals(signal_checker)
934 # call their notify signals and check sentinel
935 objects = builder.get_objects()
936 self.assertEqual(len(objects), 2)
937 for obj in objects:
938 obj.emit('test-signal')
940 self.assertEqual(signal_checker.sentinel, 4)
941 self.assertEqual(signal_checker.after_sentinel, 2)
944 @ignore_gi_deprecation_warnings
945 @unittest.skipUnless(Gtk, 'Gtk not available')
946 class TestTreeModel(unittest.TestCase):
947 def test_tree_model_sort(self):
948 self.assertEqual(Gtk.TreeModelSort, gi.overrides.Gtk.TreeModelSort)
949 model = Gtk.TreeStore(int, bool)
950 model_sort = Gtk.TreeModelSort(model=model)
951 self.assertEqual(model_sort.get_model(), model)
953 def test_tree_store(self):
954 self.assertEqual(Gtk.TreeStore, gi.overrides.Gtk.TreeStore)
955 self.assertEqual(Gtk.ListStore, gi.overrides.Gtk.ListStore)
956 self.assertEqual(Gtk.TreeModel, gi.overrides.Gtk.TreeModel)
957 self.assertEqual(Gtk.TreeViewColumn, gi.overrides.Gtk.TreeViewColumn)
959 class TestPyObject(object):
960 pass
962 test_pyobj = TestPyObject()
963 test_pydict = {1: 1, "2": 2, "3": "3"}
964 test_pylist = [1, "2", "3"]
965 tree_store = Gtk.TreeStore(int,
966 'gchararray',
967 TestGtk.TestClass,
968 GObject.TYPE_PYOBJECT,
969 object,
970 object,
971 object,
972 bool,
973 bool,
974 GObject.TYPE_UINT,
975 GObject.TYPE_ULONG,
976 GObject.TYPE_INT64,
977 GObject.TYPE_UINT64,
978 GObject.TYPE_UCHAR,
979 GObject.TYPE_CHAR)
981 parent = None
982 for i in range(97):
983 label = 'this is child #%d' % i
984 testobj = TestGtk.TestClass(self, i, label)
985 parent = tree_store.append(parent, (i,
986 label,
987 testobj,
988 testobj,
989 test_pyobj,
990 test_pydict,
991 test_pylist,
992 i % 2,
993 bool(i % 2),
995 GLib.MAXULONG,
996 GLib.MININT64,
997 0xffffffffffffffff,
998 254,
999 b'a'
1001 # test set
1002 parent = tree_store.append(parent)
1003 i = 97
1004 label = 'this is child #%d' % i
1005 testobj = TestGtk.TestClass(self, i, label)
1006 tree_store.set(parent,
1007 0, i,
1008 2, testobj,
1009 1, label,
1010 3, testobj,
1011 4, test_pyobj,
1012 5, test_pydict,
1013 6, test_pylist,
1014 7, i % 2,
1015 8, bool(i % 2),
1016 9, i,
1017 10, GLib.MAXULONG,
1018 11, GLib.MININT64,
1019 12, 0xffffffffffffffff,
1020 13, 254,
1021 14, b'a')
1023 parent = tree_store.append(parent)
1024 i = 98
1025 label = 'this is child #%d' % i
1026 testobj = TestGtk.TestClass(self, i, label)
1027 tree_store.set(parent, {0: i,
1028 2: testobj,
1029 1: label,
1030 3: testobj,
1031 4: test_pyobj,
1032 5: test_pydict,
1033 6: test_pylist,
1034 7: i % 2,
1035 8: bool(i % 2),
1036 9: i,
1037 10: GLib.MAXULONG,
1038 11: GLib.MININT64,
1039 12: 0xffffffffffffffff,
1040 13: 254,
1041 14: b'a'})
1043 parent = tree_store.append(parent)
1044 i = 99
1045 label = 'this is child #%d' % i
1046 testobj = TestGtk.TestClass(self, i, label)
1047 tree_store.set(parent, (0, 2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14),
1049 testobj,
1050 label,
1051 testobj,
1052 test_pyobj,
1053 test_pydict,
1054 test_pylist,
1055 i % 2,
1056 bool(i % 2),
1058 GLib.MAXULONG,
1059 GLib.MININT64,
1060 0xffffffffffffffff,
1061 254,
1062 b'a'))
1064 # len gets the number of children in the root node
1065 # since we kept appending to the previous node
1066 # there should only be one child of the root
1067 self.assertEqual(len(tree_store), 1)
1069 # walk the tree to see if the values were stored correctly
1070 parent = None
1071 i = 0
1073 treeiter = tree_store.iter_children(parent)
1074 while treeiter:
1075 i = tree_store.get_value(treeiter, 0)
1076 s = tree_store.get_value(treeiter, 1)
1077 obj = tree_store.get_value(treeiter, 2)
1078 obj.check(i, s)
1079 obj2 = tree_store.get_value(treeiter, 3)
1080 self.assertEqual(obj, obj2)
1082 pyobj = tree_store.get_value(treeiter, 4)
1083 self.assertEqual(pyobj, test_pyobj)
1084 pydict = tree_store.get_value(treeiter, 5)
1085 self.assertEqual(pydict, test_pydict)
1086 pylist = tree_store.get_value(treeiter, 6)
1087 self.assertEqual(pylist, test_pylist)
1089 bool_1 = tree_store.get_value(treeiter, 7)
1090 bool_2 = tree_store.get_value(treeiter, 8)
1091 self.assertEqual(bool_1, bool_2)
1092 self.assertTrue(isinstance(bool_1, bool))
1093 self.assertTrue(isinstance(bool_2, bool))
1095 uint_ = tree_store.get_value(treeiter, 9)
1096 self.assertEqual(uint_, i)
1097 ulong_ = tree_store.get_value(treeiter, 10)
1098 self.assertEqual(ulong_, GLib.MAXULONG)
1099 int64_ = tree_store.get_value(treeiter, 11)
1100 self.assertEqual(int64_, GLib.MININT64)
1101 uint64_ = tree_store.get_value(treeiter, 12)
1102 self.assertEqual(uint64_, 0xffffffffffffffff)
1103 uchar_ = tree_store.get_value(treeiter, 13)
1104 self.assertEqual(ord(uchar_), 254)
1105 char_ = tree_store.get_value(treeiter, 14)
1106 self.assertEqual(char_, 'a')
1108 parent = treeiter
1109 treeiter = tree_store.iter_children(parent)
1111 self.assertEqual(i, 99)
1113 def test_tree_store_signals(self):
1114 tree_store = Gtk.TreeStore(int, bool)
1116 def on_row_inserted(tree_store, tree_path, tree_iter, signal_list):
1117 signal_list.append('row-inserted')
1119 def on_row_changed(tree_store, tree_path, tree_iter, signal_list):
1120 signal_list.append('row-changed')
1122 signals = []
1123 tree_store.connect('row-inserted', on_row_inserted, signals)
1124 tree_store.connect('row-changed', on_row_changed, signals)
1126 # adding rows with and without data should only call one signal
1127 tree_store.append(None, (0, False))
1128 self.assertEqual(signals, ['row-inserted'])
1130 signals.pop()
1131 tree_store.append(None)
1132 self.assertEqual(signals, ['row-inserted'])
1134 signals.pop()
1135 tree_store.prepend(None, (0, False))
1136 self.assertEqual(signals, ['row-inserted'])
1138 signals.pop()
1139 tree_store.prepend(None)
1140 self.assertEqual(signals, ['row-inserted'])
1142 signals.pop()
1143 tree_store.insert(None, 1, (0, False))
1144 self.assertEqual(signals, ['row-inserted'])
1146 signals.pop()
1147 tree_store.insert(None, 1)
1148 self.assertEqual(signals, ['row-inserted'])
1150 # One set one signal
1151 signals.pop()
1152 tree_iter = tree_store.append(None, (10, False))
1153 tree_store.set(tree_iter, (0, 1), (20, True))
1154 self.assertEqual(signals, ['row-inserted', 'row-changed'])
1156 def test_list_store(self):
1157 class TestPyObject(object):
1158 pass
1160 test_pyobj = TestPyObject()
1161 test_pydict = {1: 1, "2": 2, "3": "3"}
1162 test_pylist = [1, "2", "3"]
1164 list_store = Gtk.ListStore(int, str, 'GIOverrideTreeAPITest', object, object, object, bool, bool)
1165 for i in range(1, 93):
1166 label = 'this is row #%d' % i
1167 testobj = TestGtk.TestClass(self, i, label)
1168 list_store.append((i,
1169 label,
1170 testobj,
1171 test_pyobj,
1172 test_pydict,
1173 test_pylist,
1174 i % 2,
1175 bool(i % 2)))
1177 i = 93
1178 label = u'this is row #93'
1179 treeiter = list_store.append()
1180 list_store.set_value(treeiter, 0, i)
1181 list_store.set_value(treeiter, 1, label)
1182 list_store.set_value(treeiter, 2, TestGtk.TestClass(self, i, label))
1183 list_store.set_value(treeiter, 3, test_pyobj)
1184 list_store.set_value(treeiter, 4, test_pydict)
1185 list_store.set_value(treeiter, 5, test_pylist)
1186 list_store.set_value(treeiter, 6, 1)
1187 list_store.set_value(treeiter, 7, True)
1189 # test prepend
1190 label = 'this is row #0'
1191 list_store.prepend((0,
1192 label,
1193 TestGtk.TestClass(self, 0, label),
1194 test_pyobj,
1195 test_pydict,
1196 test_pylist,
1198 False))
1200 # test automatic unicode->str conversion
1201 i = 94
1202 label = u'this is row #94'
1203 treeiter = list_store.append((i,
1204 label,
1205 TestGtk.TestClass(self, i, label),
1206 test_pyobj,
1207 test_pydict,
1208 test_pylist,
1210 False))
1212 # add sorted items out of order to test insert* apis
1213 # also test sending in None to not set a column
1214 i = 97
1215 label = 'this is row #97'
1216 treeiter = list_store.append((None,
1217 None,
1218 None,
1219 test_pyobj,
1220 None,
1221 test_pylist,
1223 None))
1225 list_store.set_value(treeiter, 0, i)
1226 list_store.set_value(treeiter, 1, label)
1227 list_store.set_value(treeiter, 2, TestGtk.TestClass(self, i, label))
1228 list_store.set_value(treeiter, 4, test_pydict)
1229 list_store.set_value(treeiter, 7, True)
1231 # this should append
1232 i = 99
1233 label = 'this is row #99'
1234 list_store.insert(9999, (i,
1235 label,
1236 TestGtk.TestClass(self, i, label),
1237 test_pyobj,
1238 test_pydict,
1239 test_pylist,
1241 True))
1243 i = 96
1244 label = 'this is row #96'
1245 list_store.insert_before(treeiter, (i,
1246 label,
1247 TestGtk.TestClass(self, i, label),
1248 test_pyobj,
1249 test_pydict,
1250 test_pylist,
1252 False))
1254 i = 98
1255 label = 'this is row #98'
1256 list_store.insert_after(treeiter, (i,
1257 label,
1258 TestGtk.TestClass(self, i, label),
1259 test_pyobj,
1260 test_pydict,
1261 test_pylist,
1263 False))
1265 i = 95
1266 label = 'this is row #95'
1267 list_store.insert(95, (i,
1268 label,
1269 TestGtk.TestClass(self, i, label),
1270 test_pyobj,
1271 test_pydict,
1272 test_pylist,
1274 True))
1276 i = 100
1277 label = 'this is row #100'
1278 treeiter = list_store.append()
1279 list_store.set(treeiter,
1280 1, label,
1281 0, i,
1282 2, TestGtk.TestClass(self, i, label),
1283 3, test_pyobj,
1284 4, test_pydict,
1285 5, test_pylist,
1286 6, 0,
1287 7, False)
1288 i = 101
1289 label = 'this is row #101'
1290 treeiter = list_store.append()
1291 list_store.set(treeiter, {1: label,
1292 0: i,
1293 2: TestGtk.TestClass(self, i, label),
1294 3: test_pyobj,
1295 4: test_pydict,
1296 5: test_pylist,
1297 6: 1,
1298 7: True})
1299 i = 102
1300 label = 'this is row #102'
1301 treeiter = list_store.append()
1302 list_store.set(treeiter, (1, 0, 2, 3, 4, 5, 6, 7),
1303 (label,
1305 TestGtk.TestClass(self, i, label),
1306 test_pyobj,
1307 test_pydict,
1308 test_pylist,
1310 False))
1312 self.assertEqual(len(list_store), 103)
1314 # walk the list to see if the values were stored correctly
1315 i = 0
1316 treeiter = list_store.get_iter_first()
1318 counter = 0
1319 while treeiter:
1320 i = list_store.get_value(treeiter, 0)
1321 self.assertEqual(i, counter)
1322 s = list_store.get_value(treeiter, 1)
1323 obj = list_store.get_value(treeiter, 2)
1324 obj.check(i, s)
1326 pyobj = list_store.get_value(treeiter, 3)
1327 self.assertEqual(pyobj, test_pyobj)
1328 pydict = list_store.get_value(treeiter, 4)
1329 self.assertEqual(pydict, test_pydict)
1330 pylist = list_store.get_value(treeiter, 5)
1331 self.assertEqual(pylist, test_pylist)
1333 bool_1 = list_store.get_value(treeiter, 6)
1334 bool_2 = list_store.get_value(treeiter, 7)
1335 self.assertEqual(bool_1, bool_2)
1336 self.assertTrue(isinstance(bool_1, bool))
1337 self.assertTrue(isinstance(bool_2, bool))
1339 treeiter = list_store.iter_next(treeiter)
1341 counter += 1
1343 self.assertEqual(i, 102)
1345 def test_list_store_sort(self):
1346 def comp1(model, row1, row2, user_data):
1347 v1 = model[row1][1]
1348 v2 = model[row2][1]
1350 # make "m" smaller than anything else
1351 if v1.startswith('m') and not v2.startswith('m'):
1352 return -1
1353 if v2.startswith('m') and not v1.startswith('m'):
1354 return 1
1355 return (v1 > v2) - (v1 < v2)
1357 list_store = Gtk.ListStore(int, str)
1358 list_store.set_sort_func(2, comp1, None)
1359 list_store.append((1, 'apples'))
1360 list_store.append((3, 'oranges'))
1361 list_store.append((2, 'mango'))
1363 # not sorted yet, should be original order
1364 self.assertEqual([list(i) for i in list_store],
1365 [[1, 'apples'], [3, 'oranges'], [2, 'mango']])
1367 # sort with our custom function
1368 list_store.set_sort_column_id(2, Gtk.SortType.ASCENDING)
1369 self.assertEqual([list(i) for i in list_store],
1370 [[2, 'mango'], [1, 'apples'], [3, 'oranges']])
1372 list_store.set_sort_column_id(2, Gtk.SortType.DESCENDING)
1373 self.assertEqual([list(i) for i in list_store],
1374 [[3, 'oranges'], [1, 'apples'], [2, 'mango']])
1376 def test_list_store_signals(self):
1377 list_store = Gtk.ListStore(int, bool)
1379 def on_row_inserted(list_store, tree_path, tree_iter, signal_list):
1380 signal_list.append('row-inserted')
1382 def on_row_changed(list_store, tree_path, tree_iter, signal_list):
1383 signal_list.append('row-changed')
1385 signals = []
1386 list_store.connect('row-inserted', on_row_inserted, signals)
1387 list_store.connect('row-changed', on_row_changed, signals)
1389 # adding rows with and without data should only call one signal
1390 list_store.append((0, False))
1391 self.assertEqual(signals, ['row-inserted'])
1393 signals.pop()
1394 list_store.append()
1395 self.assertEqual(signals, ['row-inserted'])
1397 signals.pop()
1398 list_store.prepend((0, False))
1399 self.assertEqual(signals, ['row-inserted'])
1401 signals.pop()
1402 list_store.prepend()
1403 self.assertEqual(signals, ['row-inserted'])
1405 signals.pop()
1406 list_store.insert(1, (0, False))
1407 self.assertEqual(signals, ['row-inserted'])
1409 signals.pop()
1410 list_store.insert(1)
1411 self.assertEqual(signals, ['row-inserted'])
1413 # One set one signal
1414 signals.pop()
1415 tree_iter = list_store.append((10, False))
1416 list_store.set(tree_iter, (0, 1), (20, True))
1417 self.assertEqual(signals, ['row-inserted', 'row-changed'])
1419 def test_list_store_insert_before(self):
1420 store = Gtk.ListStore(object)
1421 signals = []
1423 def on_row_inserted(store, tree_path, tree_iter, signal_list):
1424 signal_list.append('row-inserted')
1426 def on_row_changed(store, tree_path, tree_iter, signal_list):
1427 signal_list.append('row-changed')
1429 store.connect('row-inserted', on_row_inserted, signals)
1430 store.connect('row-changed', on_row_changed, signals)
1432 iter_ = store.append([0])
1433 assert store.get_value(iter_, 0) == 0
1434 assert signals == ['row-inserted']
1435 del signals[:]
1437 # append empty
1438 iter_ = store.insert_before(None)
1439 assert store.get_path(iter_).get_indices() == [1]
1440 assert store.get_value(iter_, 0) is None
1441 assert signals == ['row-inserted']
1442 del signals[:]
1444 # insert empty
1445 iter_ = store.insert_before(iter_)
1446 assert store.get_path(iter_).get_indices() == [1]
1447 assert store.get_value(iter_, 0) is None
1448 assert signals == ['row-inserted']
1449 del signals[:]
1451 # append non-empty
1452 iter_ = store.insert_before(None, [1234])
1453 assert store.get_path(iter_).get_indices() == [3]
1454 assert store.get_value(iter_, 0) == 1234
1455 assert signals == ['row-inserted']
1456 del signals[:]
1458 # insert non-empty
1459 iter_ = store.insert_before(iter_, [4321])
1460 assert store.get_path(iter_).get_indices() == [3]
1461 assert store.get_value(iter_, 0) == 4321
1462 assert signals == ['row-inserted']
1463 del signals[:]
1465 assert [r[0] for r in store] == [0, None, None, 4321, 1234]
1467 def test_list_store_insert_after(self):
1468 store = Gtk.ListStore(object)
1469 signals = []
1471 def on_row_inserted(store, tree_path, tree_iter, signal_list):
1472 signal_list.append('row-inserted')
1474 def on_row_changed(store, tree_path, tree_iter, signal_list):
1475 signal_list.append('row-changed')
1477 store.connect('row-inserted', on_row_inserted, signals)
1478 store.connect('row-changed', on_row_changed, signals)
1480 iter_ = store.append([0])
1481 assert store.get_value(iter_, 0) == 0
1482 assert signals == ['row-inserted']
1483 del signals[:]
1485 # prepend empty
1486 iter_ = store.insert_after(None)
1487 assert store.get_path(iter_).get_indices() == [0]
1488 assert store.get_value(iter_, 0) is None
1489 assert signals == ['row-inserted']
1490 del signals[:]
1492 # insert empty
1493 iter_ = store.insert_after(iter_)
1494 assert store.get_path(iter_).get_indices() == [1]
1495 assert store.get_value(iter_, 0) is None
1496 assert signals == ['row-inserted']
1497 del signals[:]
1499 # prepend non-empty
1500 iter_ = store.insert_after(None, [1234])
1501 assert store.get_path(iter_).get_indices() == [0]
1502 assert store.get_value(iter_, 0) == 1234
1503 assert signals == ['row-inserted']
1504 del signals[:]
1506 # insert non-empty
1507 iter_ = store.insert_after(iter_, [4321])
1508 assert store.get_path(iter_).get_indices() == [1]
1509 assert store.get_value(iter_, 0) == 4321
1510 assert signals == ['row-inserted']
1511 del signals[:]
1513 assert [r[0] for r in store] == [1234, 4321, None, None, 0]
1515 def test_tree_store_insert_before(self):
1516 store = Gtk.TreeStore(object)
1517 signals = []
1519 def on_row_inserted(store, tree_path, tree_iter, signal_list):
1520 signal_list.append('row-inserted')
1522 def on_row_changed(store, tree_path, tree_iter, signal_list):
1523 signal_list.append('row-changed')
1525 store.connect('row-inserted', on_row_inserted, signals)
1526 store.connect('row-changed', on_row_changed, signals)
1528 parent = store.append(None, [-1])
1529 assert signals == ['row-inserted']
1530 del signals[:]
1532 iter_ = store.append(parent, [0])
1533 assert store.get_path(iter_).get_indices() == [0, 0]
1534 assert store.get_value(iter_, 0) == 0
1535 assert signals == ['row-inserted']
1536 del signals[:]
1538 # append empty
1539 iter_ = store.insert_before(parent, None)
1540 assert store.get_path(iter_).get_indices() == [0, 1]
1541 assert store.get_value(iter_, 0) is None
1542 assert signals == ['row-inserted']
1543 del signals[:]
1545 # insert empty
1546 iter_ = store.insert_before(parent, iter_)
1547 assert store.get_path(iter_).get_indices() == [0, 1]
1548 assert store.get_value(iter_, 0) is None
1549 assert signals == ['row-inserted']
1550 del signals[:]
1552 # append non-empty
1553 iter_ = store.insert_before(parent, None, [1234])
1554 assert store.get_path(iter_).get_indices() == [0, 3]
1555 assert store.get_value(iter_, 0) == 1234
1556 assert signals == ['row-inserted']
1557 del signals[:]
1559 # insert non-empty
1560 iter_ = store.insert_before(parent, iter_, [4321])
1561 assert store.get_path(iter_).get_indices() == [0, 3]
1562 assert store.get_value(iter_, 0) == 4321
1563 assert signals == ['row-inserted']
1564 del signals[:]
1566 def func(model, path, iter_, rows):
1567 rows.append((path.get_indices(), model[iter_][:]))
1569 rows = []
1570 store.foreach(func, rows)
1571 assert rows == [
1572 ([0], [-1]), ([0, 0], [0]), ([0, 1], [None]), ([0, 2], [None]),
1573 ([0, 3], [4321]), ([0, 4], [1234])]
1575 def test_tree_store_insert_after(self):
1576 store = Gtk.TreeStore(object)
1577 signals = []
1579 def on_row_inserted(store, tree_path, tree_iter, signal_list):
1580 signal_list.append('row-inserted')
1582 def on_row_changed(store, tree_path, tree_iter, signal_list):
1583 signal_list.append('row-changed')
1585 store.connect('row-inserted', on_row_inserted, signals)
1586 store.connect('row-changed', on_row_changed, signals)
1588 parent = store.append(None, [-1])
1589 assert signals == ['row-inserted']
1590 del signals[:]
1592 iter_ = store.append(parent, [0])
1593 assert store.get_path(iter_).get_indices() == [0, 0]
1594 assert store.get_value(iter_, 0) == 0
1595 assert signals == ['row-inserted']
1596 del signals[:]
1598 # append empty
1599 iter_ = store.insert_after(parent, None)
1600 assert store.get_path(iter_).get_indices() == [0, 0]
1601 assert store.get_value(iter_, 0) is None
1602 assert signals == ['row-inserted']
1603 del signals[:]
1605 # insert empty
1606 iter_ = store.insert_after(parent, iter_)
1607 assert store.get_path(iter_).get_indices() == [0, 1]
1608 assert store.get_value(iter_, 0) is None
1609 assert signals == ['row-inserted']
1610 del signals[:]
1612 # append non-empty
1613 iter_ = store.insert_after(parent, None, [1234])
1614 assert store.get_path(iter_).get_indices() == [0, 0]
1615 assert store.get_value(iter_, 0) == 1234
1616 assert signals == ['row-inserted']
1617 del signals[:]
1619 # insert non-empty
1620 iter_ = store.insert_after(parent, iter_, [4321])
1621 assert store.get_path(iter_).get_indices() == [0, 1]
1622 assert store.get_value(iter_, 0) == 4321
1623 assert signals == ['row-inserted']
1624 del signals[:]
1626 def func(model, path, iter_, rows):
1627 rows.append((path.get_indices(), model[iter_][:]))
1629 rows = []
1630 store.foreach(func, rows)
1632 assert rows == [
1633 ([0], [-1]), ([0, 0], [1234]), ([0, 1], [4321]),
1634 ([0, 2], [None]), ([0, 3], [None]), ([0, 4], [0])]
1636 def test_tree_path(self):
1637 p1 = Gtk.TreePath()
1638 p2 = Gtk.TreePath.new_first()
1639 self.assertEqual(p1, p2)
1640 self.assertEqual(str(p1), '0')
1641 self.assertEqual(len(p1), 1)
1642 p1 = Gtk.TreePath(2)
1643 p2 = Gtk.TreePath.new_from_string('2')
1644 self.assertEqual(p1, p2)
1645 self.assertEqual(str(p1), '2')
1646 self.assertEqual(len(p1), 1)
1647 p1 = Gtk.TreePath('1:2:3')
1648 p2 = Gtk.TreePath.new_from_string('1:2:3')
1649 self.assertEqual(p1, p2)
1650 self.assertEqual(str(p1), '1:2:3')
1651 self.assertEqual(len(p1), 3)
1652 p1 = Gtk.TreePath((1, 2, 3))
1653 p2 = Gtk.TreePath.new_from_string('1:2:3')
1654 self.assertEqual(p1, p2)
1655 self.assertEqual(str(p1), '1:2:3')
1656 self.assertEqual(len(p1), 3)
1657 self.assertNotEqual(p1, None)
1658 self.assertTrue(p1 > None)
1659 self.assertTrue(p1 >= None)
1660 self.assertFalse(p1 < None)
1661 self.assertFalse(p1 <= None)
1663 self.assertEqual(tuple(p1), (1, 2, 3))
1664 self.assertEqual(p1[0], 1)
1665 self.assertEqual(p1[1], 2)
1666 self.assertEqual(p1[2], 3)
1667 self.assertRaises(IndexError, p1.__getitem__, 3)
1669 def test_tree_path_empty(self):
1670 p1 = Gtk.TreePath.new()
1671 assert str(p1) == ""
1673 def test_tree_model(self):
1674 tree_store = Gtk.TreeStore(int, str)
1676 self.assertTrue(tree_store)
1677 self.assertEqual(len(tree_store), 0)
1678 self.assertEqual(tree_store.get_iter_first(), None)
1680 def get_by_index(row, col=None):
1681 if col:
1682 return tree_store[row][col]
1683 else:
1684 return tree_store[row]
1686 self.assertRaises(TypeError, get_by_index, None)
1687 self.assertRaises(TypeError, get_by_index, "")
1688 self.assertRaises(TypeError, get_by_index, ())
1690 self.assertRaises(IndexError, get_by_index, "0")
1691 self.assertRaises(IndexError, get_by_index, 0)
1692 self.assertRaises(IndexError, get_by_index, (0,))
1694 self.assertRaises(ValueError, tree_store.get_iter, "0")
1695 self.assertRaises(ValueError, tree_store.get_iter, 0)
1696 self.assertRaises(ValueError, tree_store.get_iter, (0,))
1698 self.assertRaises(ValueError, tree_store.get_iter_from_string, "0")
1700 for row in tree_store:
1701 self.fail("Should not be reached")
1703 class DerivedIntType(int):
1704 pass
1706 class DerivedStrType(str):
1707 pass
1709 for i in range(100):
1710 label = 'this is row #%d' % i
1711 parent = tree_store.append(None, (DerivedIntType(i), DerivedStrType(label),))
1712 self.assertNotEqual(parent, None)
1713 for j in range(20):
1714 label = 'this is child #%d of node #%d' % (j, i)
1715 child = tree_store.append(parent, (j, label,))
1716 self.assertNotEqual(child, None)
1718 self.assertTrue(tree_store)
1719 self.assertEqual(len(tree_store), 100)
1721 self.assertEqual(tree_store.iter_previous(tree_store.get_iter(0)), None)
1723 for i, row in enumerate(tree_store):
1724 self.assertEqual(row.model, tree_store)
1725 self.assertEqual(row.parent, None)
1727 self.assertEqual(tree_store[i].path, row.path)
1728 self.assertEqual(tree_store[str(i)].path, row.path)
1729 self.assertEqual(tree_store[(i,)].path, row.path)
1731 self.assertEqual(tree_store[i][0], i)
1732 self.assertEqual(tree_store[i][1], "this is row #%d" % i)
1734 aiter = tree_store.get_iter(i)
1735 self.assertEqual(tree_store.get_path(aiter), row.path)
1737 aiter = tree_store.get_iter(str(i))
1738 self.assertEqual(tree_store.get_path(aiter), row.path)
1740 aiter = tree_store.get_iter((i,))
1741 self.assertEqual(tree_store.get_path(aiter), row.path)
1743 self.assertEqual(tree_store.iter_parent(aiter), row.parent)
1745 next = tree_store.iter_next(aiter)
1746 if i < len(tree_store) - 1:
1747 self.assertEqual(tree_store.get_path(next), row.next.path)
1748 self.assertEqual(tree_store.get_path(tree_store.iter_previous(next)),
1749 tree_store.get_path(aiter))
1750 else:
1751 self.assertEqual(next, None)
1753 self.assertEqual(tree_store.iter_n_children(row.iter), 20)
1755 child = tree_store.iter_children(row.iter)
1756 for j, childrow in enumerate(row.iterchildren()):
1757 child_path = tree_store.get_path(child)
1758 self.assertEqual(childrow.path, child_path)
1759 self.assertEqual(childrow.parent.path, row.path)
1760 self.assertEqual(childrow.path, tree_store[child].path)
1761 self.assertEqual(childrow.path, tree_store[child_path].path)
1763 self.assertEqual(childrow[0], tree_store[child][0])
1764 self.assertEqual(childrow[0], j)
1765 self.assertEqual(childrow[1], tree_store[child][1])
1766 self.assertEqual(childrow[1], 'this is child #%d of node #%d' % (j, i))
1768 self.assertRaises(IndexError, get_by_index, child, 2)
1770 tree_store[child][1] = 'this was child #%d of node #%d' % (j, i)
1771 self.assertEqual(childrow[1], 'this was child #%d of node #%d' % (j, i))
1773 nth_child = tree_store.iter_nth_child(row.iter, j)
1774 self.assertEqual(childrow.path, tree_store.get_path(nth_child))
1776 childrow2 = tree_store["%d:%d" % (i, j)]
1777 self.assertEqual(childrow.path, childrow2.path)
1779 childrow2 = tree_store[(i, j,)]
1780 self.assertEqual(childrow.path, childrow2.path)
1782 child = tree_store.iter_next(child)
1783 if j < 19:
1784 self.assertEqual(childrow.next.path, tree_store.get_path(child))
1785 else:
1786 self.assertEqual(child, childrow.next)
1787 self.assertEqual(child, None)
1789 self.assertEqual(j, 19)
1791 self.assertEqual(i, 99)
1793 # negative indices
1794 for i in range(-1, -100, -1):
1795 i_real = i + 100
1796 self.assertEqual(tree_store[i][0], i_real)
1798 row = tree_store[i]
1799 for j in range(-1, -20, -1):
1800 j_real = j + 20
1801 path = (i_real, j_real,)
1803 self.assertEqual(tree_store[path][-2], j_real)
1805 label = 'this was child #%d of node #%d' % (j_real, i_real)
1806 self.assertEqual(tree_store[path][-1], label)
1808 new_label = 'this still is child #%d of node #%d' % (j_real, i_real)
1809 tree_store[path][-1] = new_label
1810 self.assertEqual(tree_store[path][-1], new_label)
1812 self.assertRaises(IndexError, get_by_index, path, -3)
1814 self.assertRaises(IndexError, get_by_index, -101)
1816 last_row = tree_store[99]
1817 self.assertNotEqual(last_row, None)
1819 for i, childrow in enumerate(last_row.iterchildren()):
1820 if i < 19:
1821 self.assertTrue(tree_store.remove(childrow.iter))
1822 else:
1823 self.assertFalse(tree_store.remove(childrow.iter))
1825 self.assertEqual(i, 19)
1827 self.assertEqual(tree_store.iter_n_children(last_row.iter), 0)
1828 for childrow in last_row.iterchildren():
1829 self.fail("Should not be reached")
1831 aiter = tree_store.get_iter(10)
1832 self.assertRaises(TypeError, tree_store.get, aiter, 1, 'a')
1833 self.assertRaises(ValueError, tree_store.get, aiter, 1, -1)
1834 self.assertRaises(ValueError, tree_store.get, aiter, 1, 100)
1835 self.assertEqual(tree_store.get(aiter, 0, 1), (10, 'this is row #10'))
1837 # check __delitem__
1838 self.assertEqual(len(tree_store), 100)
1839 aiter = tree_store.get_iter(10)
1840 del tree_store[aiter]
1841 self.assertEqual(len(tree_store), 99)
1842 self.assertRaises(TypeError, tree_store.__delitem__, None)
1843 self.assertRaises(IndexError, tree_store.__delitem__, -101)
1844 self.assertRaises(IndexError, tree_store.__delitem__, 101)
1846 def test_tree_model_get_iter_fail(self):
1847 # TreeModel class with a failing get_iter()
1848 class MyTreeModel(GObject.GObject, Gtk.TreeModel):
1849 def do_get_iter(self, iter):
1850 return (False, None)
1852 tm = MyTreeModel()
1853 self.assertEqual(tm.get_iter_first(), None)
1855 def test_tree_model_edit(self):
1856 model = Gtk.ListStore(int, str, float)
1857 model.append([1, "one", -0.1])
1858 model.append([2, "two", -0.2])
1860 def set_row(value):
1861 model[1] = value
1863 self.assertRaises(TypeError, set_row, 3)
1864 self.assertRaises(TypeError, set_row, "three")
1865 self.assertRaises(ValueError, set_row, [])
1866 self.assertRaises(ValueError, set_row, [3, "three"])
1868 model[0] = (3, "three", -0.3)
1870 def test_tree_row_slice(self):
1871 model = Gtk.ListStore(int, str, float)
1872 model.append([1, "one", -0.1])
1874 self.assertEqual([1, "one", -0.1], model[0][:])
1875 self.assertEqual([1, "one"], model[0][:2])
1876 self.assertEqual(["one", -0.1], model[0][1:])
1877 self.assertEqual(["one"], model[0][1:-1])
1878 self.assertEqual([1], model[0][:-2])
1879 self.assertEqual([], model[0][5:])
1880 self.assertEqual([1, -0.1], model[0][0:3:2])
1882 model[0][:] = (2, "two", -0.2)
1883 self.assertEqual([2, "two", -0.2], model[0][:])
1885 model[0][:2] = (3, "three")
1886 self.assertEqual([3, "three", -0.2], model[0][:])
1888 model[0][1:] = ("four", -0.4)
1889 self.assertEqual([3, "four", -0.4], model[0][:])
1891 model[0][1:-1] = ("five",)
1892 self.assertEqual([3, "five", -0.4], model[0][:])
1894 model[0][0:3:2] = (6, -0.6)
1895 self.assertEqual([6, "five", -0.6], model[0][:])
1897 def set_row1():
1898 model[0][5:] = ("doesn't", "matter",)
1900 self.assertRaises(ValueError, set_row1)
1902 def set_row2():
1903 model[0][:1] = (0, "zero", 0)
1905 self.assertRaises(ValueError, set_row2)
1907 def set_row3():
1908 model[0][:2] = ("0", 0)
1910 self.assertRaises(TypeError, set_row3)
1912 def test_tree_row_sequence(self):
1913 model = Gtk.ListStore(int, str, float)
1914 model.append([1, "one", -0.1])
1916 self.assertEqual([1, "one", -0.1], model[0][0, 1, 2])
1917 self.assertEqual([1, "one"], model[0][0, 1])
1918 self.assertEqual(["one", -0.1], model[0][1, 2])
1919 self.assertEqual("one", model[0][1])
1920 self.assertEqual([1, -0.1], model[0][0, 2])
1921 self.assertEqual([-0.1, 1], model[0][2, 0])
1923 model[0][0, 1, 2] = (2, "two", -0.2)
1924 self.assertEqual([2, "two", -0.2], model[0][0, 1, 2])
1926 model[0][0, 1] = (3, "three")
1927 self.assertEqual([3, "three"], model[0][0, 1])
1929 model[0][1, 2] = ("four", -0.4)
1930 self.assertEqual(["four", -0.4], model[0][1, 2])
1932 model[0][0, 2] = (5, -0.5)
1933 self.assertEqual([5, -0.5], model[0][0, 2])
1935 model[0][0, 1, 2] = (6, "six", -0.6)
1936 self.assertEqual([-0.6, 6, "six"], model[0][2, 0, 1])
1938 def set_row1():
1939 model[0][4, 5] = ("shouldn't", "work",)
1941 self.assertRaises(IndexError, set_row1)
1943 def set_row2():
1944 model[0][0, 1] = (0, "zero", 0)
1946 self.assertRaises(ValueError, set_row2)
1948 def set_row3():
1949 model[0][0, 1] = ("shouldn't", 0)
1951 self.assertRaises(TypeError, set_row3)
1953 def set_row4():
1954 model[0][0, "two"] = (0, "zero")
1956 self.assertRaises(TypeError, set_row4)
1958 def test_tree_model_set_value_to_none(self):
1959 # Tests allowing the usage of None to set an empty value on a model.
1960 store = Gtk.ListStore(str)
1961 row = store.append(['test'])
1962 self.assertSequenceEqual(store[0][:], ['test'])
1963 store.set_value(row, 0, None)
1964 self.assertSequenceEqual(store[0][:], [None])
1966 def test_signal_emission_tree_path_coerce(self):
1967 class Model(GObject.Object, Gtk.TreeModel):
1968 pass
1970 model = Model()
1971 tree_paths = []
1973 def on_any_signal(model, path, *args):
1974 tree_paths.append(path.to_string())
1976 model.connect('row-changed', on_any_signal)
1977 model.connect('row-deleted', on_any_signal)
1978 model.connect('row-has-child-toggled', on_any_signal)
1979 model.connect('row-inserted', on_any_signal)
1981 model.row_changed('0', Gtk.TreeIter())
1982 self.assertEqual(tree_paths[-1], '0')
1984 model.row_deleted('1')
1985 self.assertEqual(tree_paths[-1], '1')
1987 model.row_has_child_toggled('2', Gtk.TreeIter())
1988 self.assertEqual(tree_paths[-1], '2')
1990 model.row_inserted('3', Gtk.TreeIter())
1991 self.assertEqual(tree_paths[-1], '3')
1993 def test_tree_model_filter(self):
1994 model = Gtk.ListStore(int, str, float)
1995 model.append([1, "one", -0.1])
1996 model.append([2, "two", -0.2])
1998 filtered = Gtk.TreeModelFilter(child_model=model)
2000 self.assertEqual(filtered[0][1], 'one')
2001 filtered[0][1] = 'ONE'
2002 self.assertEqual(filtered[0][1], 'ONE')
2004 def test_list_store_performance(self):
2005 model = Gtk.ListStore(int, str)
2007 iterations = 2000
2008 start = time.clock()
2009 i = iterations
2010 while i > 0:
2011 model.append([1, 'hello'])
2012 i -= 1
2013 end = time.clock()
2014 sys.stderr.write('[%.0f µs/append] ' % ((end - start) * 1000000 / iterations))
2016 def test_filter_new_default(self):
2017 # Test filter_new accepts implicit default of None
2018 model = Gtk.ListStore(int)
2019 filt = model.filter_new()
2020 self.assertTrue(filt is not None)
2023 @unittest.skipIf(sys.platform == "darwin", "hangs")
2024 @unittest.skipUnless(Gtk, 'Gtk not available')
2025 class TestTreeView(unittest.TestCase):
2026 def test_tree_view(self):
2027 store = Gtk.ListStore(int, str)
2028 store.append((0, "foo"))
2029 store.append((1, "bar"))
2030 view = Gtk.TreeView()
2032 with realized(view):
2033 view.set_cursor(store[1].path)
2034 view.set_cursor(str(store[1].path))
2036 view.get_cell_area(store[1].path)
2037 view.get_cell_area(str(store[1].path))
2039 def test_tree_view_column(self):
2040 cell = Gtk.CellRendererText()
2041 col = Gtk.TreeViewColumn(title='This is just a test',
2042 cell_renderer=cell,
2043 text=0,
2044 style=2)
2046 # Regression test for: https://bugzilla.gnome.org/show_bug.cgi?id=711173
2047 col.set_cell_data_func(cell, None, None)
2049 def test_tree_view_add_column_with_attributes(self):
2050 model = Gtk.ListStore(str, str, str)
2051 # deliberately use out-of-order sorting here; we assign column 0 to
2052 # model index 2, etc.
2053 model.append(['cell13', 'cell11', 'cell12'])
2054 model.append(['cell23', 'cell21', 'cell22'])
2056 tree = Gtk.TreeView(model=model)
2057 cell1 = Gtk.CellRendererText()
2058 cell2 = Gtk.CellRendererText()
2059 cell3 = Gtk.CellRendererText()
2060 cell4 = Gtk.CellRendererText()
2062 tree.insert_column_with_attributes(0, 'Head2', cell2, text=2)
2063 tree.insert_column_with_attributes(0, 'Head1', cell1, text=1)
2064 tree.insert_column_with_attributes(-1, 'Head3', cell3, text=0)
2065 # unconnected
2066 tree.insert_column_with_attributes(-1, 'Head4', cell4)
2068 with realized(tree):
2069 tree.set_cursor(model[0].path)
2070 while Gtk.events_pending():
2071 Gtk.main_iteration()
2073 self.assertEqual(tree.get_column(0).get_title(), 'Head1')
2074 self.assertEqual(tree.get_column(1).get_title(), 'Head2')
2075 self.assertEqual(tree.get_column(2).get_title(), 'Head3')
2076 self.assertEqual(tree.get_column(3).get_title(), 'Head4')
2078 # cursor should be at the first row
2079 self.assertEqual(cell1.props.text, 'cell11')
2080 self.assertEqual(cell2.props.text, 'cell12')
2081 self.assertEqual(cell3.props.text, 'cell13')
2082 self.assertEqual(cell4.props.text, None)
2084 def test_tree_view_column_set_attributes(self):
2085 store = Gtk.ListStore(int, str)
2086 directors = ['Fellini', 'Tarantino', 'Tarkovskiy']
2087 for i, director in enumerate(directors):
2088 store.append([i, director])
2090 treeview = Gtk.TreeView()
2091 treeview.set_model(store)
2093 column = Gtk.TreeViewColumn()
2094 treeview.append_column(column)
2096 cell = Gtk.CellRendererText()
2097 column.pack_start(cell, expand=True)
2098 column.set_attributes(cell, text=1)
2100 with realized(treeview):
2101 self.assertTrue(cell.props.text in directors)
2103 def test_tree_selection(self):
2104 store = Gtk.ListStore(int, str)
2105 for i in range(10):
2106 store.append((i, "foo"))
2107 view = Gtk.TreeView()
2108 view.set_model(store)
2109 firstpath = store.get_path(store.get_iter_first())
2110 sel = view.get_selection()
2112 sel.select_path(firstpath)
2113 (m, s) = sel.get_selected()
2114 self.assertEqual(m, store)
2115 self.assertEqual(store.get_path(s), firstpath)
2117 sel.select_path(0)
2118 (m, s) = sel.get_selected()
2119 self.assertEqual(m, store)
2120 self.assertEqual(store.get_path(s), firstpath)
2122 sel.select_path("0:0")
2123 (m, s) = sel.get_selected()
2124 self.assertEqual(m, store)
2125 self.assertEqual(store.get_path(s), firstpath)
2127 sel.select_path((0, 0))
2128 (m, s) = sel.get_selected()
2129 self.assertEqual(m, store)
2130 self.assertEqual(store.get_path(s), firstpath)
2133 @unittest.skipUnless(Gtk, 'Gtk not available')
2134 class TestTextBuffer(unittest.TestCase):
2135 def test_text_buffer(self):
2136 self.assertEqual(Gtk.TextBuffer, gi.overrides.Gtk.TextBuffer)
2137 buffer = Gtk.TextBuffer()
2138 tag = buffer.create_tag('title', font='Sans 18')
2140 self.assertEqual(tag.props.name, 'title')
2141 self.assertEqual(tag.props.font, 'Sans 18')
2143 (start, end) = buffer.get_bounds()
2145 mark = buffer.create_mark(None, start)
2146 self.assertFalse(mark.get_left_gravity())
2148 buffer.set_text('Hello Jane Hello Bob')
2149 (start, end) = buffer.get_bounds()
2150 text = buffer.get_text(start, end, False)
2151 self.assertEqual(text, 'Hello Jane Hello Bob')
2153 buffer.set_text('')
2154 (start, end) = buffer.get_bounds()
2155 text = buffer.get_text(start, end, False)
2156 self.assertEqual(text, '')
2158 buffer.insert(end, 'HelloHello')
2159 buffer.insert(end, ' Bob')
2161 cursor_iter = end.copy()
2162 cursor_iter.backward_chars(9)
2163 buffer.place_cursor(cursor_iter)
2164 buffer.insert_at_cursor(' Jane ')
2166 (start, end) = buffer.get_bounds()
2167 text = buffer.get_text(start, end, False)
2168 self.assertEqual(text, 'Hello Jane Hello Bob')
2170 sel = buffer.get_selection_bounds()
2171 self.assertEqual(sel, ())
2172 buffer.select_range(start, end)
2173 sel = buffer.get_selection_bounds()
2174 self.assertTrue(sel[0].equal(start))
2175 self.assertTrue(sel[1].equal(end))
2177 buffer.set_text('')
2178 buffer.insert_with_tags(buffer.get_start_iter(), 'HelloHello')
2179 start, end = buffer.get_bounds()
2180 text = buffer.get_text(start, end, False)
2181 self.assertEqual(text, 'HelloHello')
2183 buffer.set_text('')
2184 buffer.insert_with_tags_by_name(buffer.get_start_iter(), 'HelloHello')
2185 start, end = buffer.get_bounds()
2186 text = buffer.get_text(start, end, False)
2187 self.assertEqual(text, 'HelloHello')
2189 try:
2190 starts_tag = Gtk.TextIter.starts_tag
2191 except AttributeError:
2192 starts_tag = Gtk.TextIter.begins_tag
2194 buffer.set_text('')
2195 buffer.insert_with_tags(buffer.get_start_iter(), 'HelloHello', tag)
2196 (start, end) = buffer.get_bounds()
2197 self.assertTrue(starts_tag(start, tag))
2198 self.assertTrue(start.has_tag(tag))
2200 buffer.set_text('')
2201 buffer.insert_with_tags_by_name(buffer.get_start_iter(), 'HelloHello', 'title')
2202 (start, end) = buffer.get_bounds()
2203 self.assertTrue(starts_tag(start, tag))
2204 self.assertTrue(start.has_tag(tag))
2206 self.assertRaises(ValueError, buffer.insert_with_tags_by_name,
2207 buffer.get_start_iter(), 'HelloHello', 'unknowntag')
2209 def test_text_iter(self):
2210 try:
2211 starts_tag = Gtk.TextIter.starts_tag
2212 except AttributeError:
2213 starts_tag = Gtk.TextIter.begins_tag
2215 self.assertEqual(Gtk.TextIter, gi.overrides.Gtk.TextIter)
2216 buffer = Gtk.TextBuffer()
2217 buffer.set_text('Hello Jane Hello Bob')
2218 tag = buffer.create_tag('title', font='Sans 18')
2219 (start, end) = buffer.get_bounds()
2220 start.forward_chars(10)
2221 buffer.apply_tag(tag, start, end)
2222 self.assertTrue(starts_tag(start))
2223 self.assertTrue(end.ends_tag())
2224 self.assertTrue(start.toggles_tag())
2225 self.assertTrue(end.toggles_tag())
2226 start.backward_chars(1)
2227 self.assertFalse(starts_tag(start))
2228 self.assertFalse(start.ends_tag())
2229 self.assertFalse(start.toggles_tag())
2231 def test_text_buffer_search(self):
2232 buffer = Gtk.TextBuffer()
2233 buffer.set_text('Hello World Hello GNOME')
2235 i = buffer.get_iter_at_offset(0)
2236 self.assertTrue(isinstance(i, Gtk.TextIter))
2238 self.assertEqual(i.forward_search('world', 0, None), None)
2240 (start, end) = i.forward_search('World', 0, None)
2241 self.assertEqual(start.get_offset(), 6)
2242 self.assertEqual(end.get_offset(), 11)
2244 (start, end) = i.forward_search('world',
2245 Gtk.TextSearchFlags.CASE_INSENSITIVE,
2246 None)
2247 self.assertEqual(start.get_offset(), 6)
2248 self.assertEqual(end.get_offset(), 11)
2250 def test_insert_text_signal_location_modification(self):
2251 # Regression test for: https://bugzilla.gnome.org/show_bug.cgi?id=736175
2253 def callback(buffer, location, text, length):
2254 location.assign(buffer.get_end_iter())
2256 buffer = Gtk.TextBuffer()
2257 buffer.set_text('first line\n')
2258 buffer.connect('insert-text', callback)
2260 # attempt insertion at the beginning of the buffer, the callback will
2261 # modify the insert location to the end.
2262 buffer.place_cursor(buffer.get_start_iter())
2263 buffer.insert_at_cursor('second line\n')
2265 self.assertEqual(buffer.get_property('text'),
2266 'first line\nsecond line\n')
2268 @unittest.skipIf(gtkver() < (3, 20, 0), "broken with older gtk")
2269 def test_backward_find_char(self):
2270 buffer = Gtk.TextBuffer()
2271 buffer.set_text('abc')
2272 end = buffer.get_iter_at_line(99)
2274 values = []
2276 def pred_func(ch, user_data):
2277 values.append(ch)
2278 return ch == u"a"
2280 self.assertTrue(end.backward_find_char(pred_func))
2281 self.assertEqual(values, [u"c", u"b", u"a"])
2284 @unittest.skipUnless(Gtk, 'Gtk not available')
2285 class TestContainer(unittest.TestCase):
2287 @unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
2288 def test_child_set_property(self):
2289 box = Gtk.Box()
2290 child = Gtk.Button()
2291 box.pack_start(child, expand=False, fill=True, padding=0)
2293 box.child_set_property(child, 'padding', 42)
2295 value = GObject.Value(int)
2296 box.child_get_property(child, 'padding', value)
2297 self.assertEqual(value.get_int(), 42)
2299 @unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
2300 def test_child_get_property_gvalue(self):
2301 box = Gtk.Box()
2302 child = Gtk.Button()
2303 box.pack_start(child, expand=False, fill=True, padding=42)
2305 value = GObject.Value(int)
2306 box.child_get_property(child, 'padding', value)
2307 self.assertEqual(value.get_int(), 42)
2309 @unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
2310 def test_child_get_property_return_with_explicit_gvalue(self):
2311 box = Gtk.Box()
2312 child = Gtk.Button()
2313 box.pack_start(child, expand=False, fill=True, padding=42)
2315 value = GObject.Value(int)
2316 result = box.child_get_property(child, 'padding', value)
2317 self.assertEqual(result, 42)
2319 @unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
2320 def test_child_get_property_return_with_implicit_gvalue(self):
2321 box = Gtk.Box()
2322 child = Gtk.Button()
2323 box.pack_start(child, expand=False, fill=True, padding=42)
2325 result = box.child_get_property(child, 'padding')
2326 self.assertEqual(result, 42)
2328 def test_child_get_property_error(self):
2329 box = Gtk.Box()
2330 child = Gtk.Button()
2331 if Gtk_version == "4.0":
2332 box.pack_start(child, expand=False, fill=True)
2333 else:
2334 box.pack_start(child, expand=False, fill=True, padding=42)
2335 with self.assertRaises(ValueError):
2336 box.child_get_property(child, 'not-a-valid-child-property')
2338 @unittest.skipIf(Gtk_version == "4.0", "not in gtk4")
2339 def test_child_get_and_set(self):
2340 box = Gtk.Box()
2341 child = Gtk.Button()
2342 box.pack_start(child, expand=True, fill=True, padding=42)
2344 expand, fill, padding = box.child_get(child, 'expand', 'fill', 'padding')
2345 self.assertEqual(expand, True)
2346 self.assertEqual(fill, True)
2347 self.assertEqual(padding, 42)
2349 box.child_set(child, expand=False, fill=False, padding=21, pack_type=1)
2350 expand, fill, padding, pack_type = box.child_get(child, 'expand', 'fill', 'padding', 'pack-type')
2351 self.assertEqual(expand, False)
2352 self.assertEqual(fill, False)
2353 self.assertEqual(padding, 21)
2355 @unittest.skipIf(Gtk_version != "4.0", "only in gtk4")
2356 def test_child_get_and_set_gtk4(self):
2357 # padding got removed in gtk4
2358 box = Gtk.Box()
2359 child = Gtk.Button()
2360 box.pack_start(child, expand=True, fill=True)
2362 expand, fill = box.child_get(child, 'expand', 'fill')
2363 self.assertEqual(expand, True)
2364 self.assertEqual(fill, True)
2366 box.child_set(child, expand=False, fill=False, pack_type=1)
2367 expand, fill, pack_type = box.child_get(child, 'expand', 'fill', 'pack-type')
2368 self.assertEqual(expand, False)
2369 self.assertEqual(fill, False)