1 # -*- Mode: Python; py-indent-offset: 4 -*-
3 # vim: tabstop=4 shiftwidth=4 expandtab
5 from __future__
import absolute_import
14 from .helper
import ignore_gi_deprecation_warnings
, capture_glib_warnings
18 from gi
.repository
import GLib
, GObject
21 from gi
.repository
import Gtk
, GdkPixbuf
, Gdk
22 PyGTKDeprecationWarning
= Gtk
.PyGTKDeprecationWarning
23 Gtk_version
= Gtk
._version
27 PyGTKDeprecationWarning
= None
35 return (Gtk
.get_major_version(),
36 Gtk
.get_minor_version(),
37 Gtk
.get_micro_version())
40 @contextlib.contextmanager
42 """Makes sure the widget is realized.
49 if isinstance(widget
, Gtk
.Window
):
52 toplevel
= widget
.get_parent_window()
59 while Gtk
.events_pending():
61 assert widget
.get_realized()
68 while Gtk
.events_pending():
72 @unittest.skipUnless(Gtk
, 'Gtk not available')
73 def test_freeze_child_notif():
77 def on_notify(widget
, spec
):
78 events
.append(spec
.name
)
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)
88 assert events
.count("expand") == 1
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
)
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
):
124 self
.assertTrue(isinstance(box
, Gtk
.Box
))
125 self
.assertTrue(isinstance(box
, Gtk
.Container
))
126 self
.assertTrue(isinstance(box
, Gtk
.Widget
))
132 self
.assertTrue(label
in box
)
133 self
.assertTrue(label2
in box
)
134 self
.assertEqual(len(box
), 2)
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
,
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
)
198 @unittest.skipIf(Gtk_version
== "4.0", "not in gtk4")
199 def test_uimanager(self
):
200 self
.assertEqual(Gtk
.UIManager
, gi
.overrides
.Gtk
.UIManager
)
202 ui
.add_ui_from_string("""<ui>
203 <menubar name="menubar1"></menubar>
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
):
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
):
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"
238 builder
= Gtk
.Builder()
239 builder
.add_from_string('''
241 <object class="GtkWindow" id="win">
242 <property name="type">popup</property>
244 <object class="TestWindow" id="testwin">
246 <object class="TestWindow" id="testpop">
247 <property name="type">popup</property>
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
),
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.
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',
351 buttons
=Gtk
.ButtonsType
.OK
,
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
__()
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
)
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,
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
):
463 klass
= getattr(Gtk
, element
)
464 info
= klass
.__info
__
465 except (NotImplementedError, AttributeError):
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"]
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
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
):
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)
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),
611 Gtk
.TargetEntry
.new('test2', 2, 2),
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
,
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
):
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
):
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
):
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
):
711 GLib
.idle_add(Gtk
.main_quit
)
714 # overridden function ignores its arguments
715 GLib
.idle_add(Gtk
.main_quit
, 'hello')
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
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'}
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
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()
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):
799 overlay
= Gtk
.Overlay()
800 overlay
.connect('get-child-position', get_child_position
)
802 rect
= Gdk
.Rectangle()
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"
820 "test-signal": (GObject
.SignalFlags
.RUN_FIRST
,
825 def test_extract_handler_and_args_object(self
):
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("""
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" />
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)
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
)
890 self
.after_sentinel
= 0
892 def on_signal_1(self
, *args
):
894 self
.after_sentinel
+= 1
896 def on_signal_3(self
, *args
):
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("""
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" />
916 # only add object3 to the builder
917 builder
.add_objects_from_string("""
919 <object class="GIOverrideSignalTest" id="object2">
920 <signal name="test-signal" handler="on_signal_2" />
922 <object class="GIOverrideSignalTest" id="object3">
923 <signal name="test-signal" handler="on_signal_3" />
925 <object class="GIOverrideSignalTest" id="object4">
926 <signal name="test-signal" handler="on_signal_4" />
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)
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):
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,
968 GObject
.TYPE_PYOBJECT
,
983 label
= 'this is child #%d' % i
984 testobj
= TestGtk
.TestClass(self
, i
, label
)
985 parent
= tree_store
.append(parent
, (i
,
1002 parent
= tree_store
.append(parent
)
1004 label
= 'this is child #%d' % i
1005 testobj
= TestGtk
.TestClass(self
, i
, label
)
1006 tree_store
.set(parent
,
1019 12, 0xffffffffffffffff,
1023 parent
= tree_store
.append(parent
)
1025 label
= 'this is child #%d' % i
1026 testobj
= TestGtk
.TestClass(self
, i
, label
)
1027 tree_store
.set(parent
, {0: i
,
1039 12: 0xffffffffffffffff,
1043 parent
= tree_store
.append(parent
)
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),
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
1073 treeiter
= tree_store
.iter_children(parent
)
1075 i
= tree_store
.get_value(treeiter
, 0)
1076 s
= tree_store
.get_value(treeiter
, 1)
1077 obj
= tree_store
.get_value(treeiter
, 2)
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')
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')
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'])
1131 tree_store
.append(None)
1132 self
.assertEqual(signals
, ['row-inserted'])
1135 tree_store
.prepend(None, (0, False))
1136 self
.assertEqual(signals
, ['row-inserted'])
1139 tree_store
.prepend(None)
1140 self
.assertEqual(signals
, ['row-inserted'])
1143 tree_store
.insert(None, 1, (0, False))
1144 self
.assertEqual(signals
, ['row-inserted'])
1147 tree_store
.insert(None, 1)
1148 self
.assertEqual(signals
, ['row-inserted'])
1150 # One set one signal
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):
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
,
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)
1190 label
= 'this is row #0'
1191 list_store
.prepend((0,
1193 TestGtk
.TestClass(self
, 0, label
),
1200 # test automatic unicode->str conversion
1202 label
= u
'this is row #94'
1203 treeiter
= list_store
.append((i
,
1205 TestGtk
.TestClass(self
, i
, label
),
1212 # add sorted items out of order to test insert* apis
1213 # also test sending in None to not set a column
1215 label
= 'this is row #97'
1216 treeiter
= list_store
.append((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
1233 label
= 'this is row #99'
1234 list_store
.insert(9999, (i
,
1236 TestGtk
.TestClass(self
, i
, label
),
1244 label
= 'this is row #96'
1245 list_store
.insert_before(treeiter
, (i
,
1247 TestGtk
.TestClass(self
, i
, label
),
1255 label
= 'this is row #98'
1256 list_store
.insert_after(treeiter
, (i
,
1258 TestGtk
.TestClass(self
, i
, label
),
1266 label
= 'this is row #95'
1267 list_store
.insert(95, (i
,
1269 TestGtk
.TestClass(self
, i
, label
),
1277 label
= 'this is row #100'
1278 treeiter
= list_store
.append()
1279 list_store
.set(treeiter
,
1282 2, TestGtk
.TestClass(self
, i
, label
),
1289 label
= 'this is row #101'
1290 treeiter
= list_store
.append()
1291 list_store
.set(treeiter
, {1: label
,
1293 2: TestGtk
.TestClass(self
, i
, label
),
1300 label
= 'this is row #102'
1301 treeiter
= list_store
.append()
1302 list_store
.set(treeiter
, (1, 0, 2, 3, 4, 5, 6, 7),
1305 TestGtk
.TestClass(self
, i
, label
),
1312 self
.assertEqual(len(list_store
), 103)
1314 # walk the list to see if the values were stored correctly
1316 treeiter
= list_store
.get_iter_first()
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)
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
)
1343 self
.assertEqual(i
, 102)
1345 def test_list_store_sort(self
):
1346 def comp1(model
, row1
, row2
, user_data
):
1350 # make "m" smaller than anything else
1351 if v1
.startswith('m') and not v2
.startswith('m'):
1353 if v2
.startswith('m') and not v1
.startswith('m'):
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')
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'])
1395 self
.assertEqual(signals
, ['row-inserted'])
1398 list_store
.prepend((0, False))
1399 self
.assertEqual(signals
, ['row-inserted'])
1402 list_store
.prepend()
1403 self
.assertEqual(signals
, ['row-inserted'])
1406 list_store
.insert(1, (0, False))
1407 self
.assertEqual(signals
, ['row-inserted'])
1410 list_store
.insert(1)
1411 self
.assertEqual(signals
, ['row-inserted'])
1413 # One set one signal
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)
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']
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']
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']
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']
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']
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)
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']
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']
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']
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']
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']
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)
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']
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']
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']
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']
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']
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']
1566 def func(model
, path
, iter_
, rows
):
1567 rows
.append((path
.get_indices(), model
[iter_
][:]))
1570 store
.foreach(func
, 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)
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']
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']
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']
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']
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']
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']
1626 def func(model
, path
, iter_
, rows
):
1627 rows
.append((path
.get_indices(), model
[iter_
][:]))
1630 store
.foreach(func
, 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
):
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):
1682 return tree_store
[row
][col
]
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):
1706 class DerivedStrType(str):
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)
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
))
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
)
1784 self
.assertEqual(childrow
.next
.path
, tree_store
.get_path(child
))
1786 self
.assertEqual(child
, childrow
.next
)
1787 self
.assertEqual(child
, None)
1789 self
.assertEqual(j
, 19)
1791 self
.assertEqual(i
, 99)
1794 for i
in range(-1, -100, -1):
1796 self
.assertEqual(tree_store
[i
][0], i_real
)
1799 for j
in range(-1, -20, -1):
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()):
1821 self
.assertTrue(tree_store
.remove(childrow
.iter))
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'))
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)
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])
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][:])
1898 model
[0][5:] = ("doesn't", "matter",)
1900 self
.assertRaises(ValueError, set_row1
)
1903 model
[0][:1] = (0, "zero", 0)
1905 self
.assertRaises(ValueError, set_row2
)
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])
1939 model
[0][4, 5] = ("shouldn't", "work",)
1941 self
.assertRaises(IndexError, set_row1
)
1944 model
[0][0, 1] = (0, "zero", 0)
1946 self
.assertRaises(ValueError, set_row2
)
1949 model
[0][0, 1] = ("shouldn't", 0)
1951 self
.assertRaises(TypeError, set_row3
)
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
):
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)
2008 start
= time
.clock()
2011 model
.append([1, 'hello'])
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',
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)
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)
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
)
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')
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
))
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')
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')
2190 starts_tag
= Gtk
.TextIter
.starts_tag
2191 except AttributeError:
2192 starts_tag
= Gtk
.TextIter
.begins_tag
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
))
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
):
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
,
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)
2276 def pred_func(ch
, user_data
):
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
):
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
):
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
):
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
):
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
):
2330 child
= Gtk
.Button()
2331 if Gtk_version
== "4.0":
2332 box
.pack_start(child
, expand
=False, fill
=True)
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
):
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
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)