8887da8cb4215ab970c9ec17a4b420e27256c310
[platform/upstream/pygobject2.git] / gi / overrides / Gtk.py
1 # -*- Mode: Python; py-indent-offset: 4 -*-
2 # vim: tabstop=4 shiftwidth=4 expandtab
3 #
4 # Copyright (C) 2009 Johan Dahlin <johan@gnome.org>
5 #               2010 Simon van der Linden <svdlinden@src.gnome.org>
6 #
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2.1 of the License, or (at your option) any later version.
11 #
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 # Lesser General Public License for more details.
16 #
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this library; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
20 # USA
21
22 import collections
23 import sys
24 import warnings
25
26 from gi.repository import GObject
27 from ..overrides import override, strip_boolean_result, deprecated_init
28 from ..module import get_introspection_module
29 from gi import PyGIDeprecationWarning
30
31 if sys.version_info >= (3, 0):
32     _basestring = str
33     _callable = lambda c: hasattr(c, '__call__')
34 else:
35     _basestring = basestring
36     _callable = callable
37
38 Gtk = get_introspection_module('Gtk')
39
40 __all__ = []
41
42 if Gtk._version == '2.0':
43     warn_msg = "You have imported the Gtk 2.0 module.  Because Gtk 2.0 \
44 was not designed for use with introspection some of the \
45 interfaces and API will fail.  As such this is not supported \
46 by the pygobject development team and we encourage you to \
47 port your app to Gtk 3 or greater. PyGTK is the recomended \
48 python module to use with Gtk 2.0"
49
50     warnings.warn(warn_msg, RuntimeWarning)
51
52
53 class PyGTKDeprecationWarning(PyGIDeprecationWarning):
54     pass
55
56 __all__.append('PyGTKDeprecationWarning')
57
58
59 def _construct_target_list(targets):
60     """Create a list of TargetEntry items from a list of tuples in the form (target, flags, info)
61
62     The list can also contain existing TargetEntry items in which case the existing entry
63     is re-used in the return list.
64     """
65     target_entries = []
66     for entry in targets:
67         if not isinstance(entry, Gtk.TargetEntry):
68             entry = Gtk.TargetEntry.new(*entry)
69         target_entries.append(entry)
70     return target_entries
71
72 __all__.append('_construct_target_list')
73
74
75 class Widget(Gtk.Widget):
76
77     translate_coordinates = strip_boolean_result(Gtk.Widget.translate_coordinates)
78
79     def drag_dest_set_target_list(self, target_list):
80         if (target_list is not None) and (not isinstance(target_list, Gtk.TargetList)):
81             target_list = Gtk.TargetList.new(_construct_target_list(target_list))
82         super(Widget, self).drag_dest_set_target_list(target_list)
83
84     def drag_source_set_target_list(self, target_list):
85         if (target_list is not None) and (not isinstance(target_list, Gtk.TargetList)):
86             target_list = Gtk.TargetList.new(_construct_target_list(target_list))
87         super(Widget, self).drag_source_set_target_list(target_list)
88
89
90 Widget = override(Widget)
91 __all__.append('Widget')
92
93
94 class Container(Gtk.Container, Widget):
95
96     def __len__(self):
97         return len(self.get_children())
98
99     def __contains__(self, child):
100         return child in self.get_children()
101
102     def __iter__(self):
103         return iter(self.get_children())
104
105     def __bool__(self):
106         return True
107
108     # alias for Python 2.x object protocol
109     __nonzero__ = __bool__
110
111     get_focus_chain = strip_boolean_result(Gtk.Container.get_focus_chain)
112
113
114 Container = override(Container)
115 __all__.append('Container')
116
117
118 class Editable(Gtk.Editable):
119
120     def insert_text(self, text, position):
121         return super(Editable, self).insert_text(text, -1, position)
122
123     get_selection_bounds = strip_boolean_result(Gtk.Editable.get_selection_bounds, fail_ret=())
124
125
126 Editable = override(Editable)
127 __all__.append("Editable")
128
129
130 class Action(Gtk.Action):
131     __init__ = deprecated_init(Gtk.Action.__init__,
132                                arg_names=('name', 'label', 'tooltip', 'stock_id'),
133                                category=PyGTKDeprecationWarning)
134
135 Action = override(Action)
136 __all__.append("Action")
137
138
139 class RadioAction(Gtk.RadioAction):
140     __init__ = deprecated_init(Gtk.RadioAction.__init__,
141                                arg_names=('name', 'label', 'tooltip', 'stock_id', 'value'),
142                                category=PyGTKDeprecationWarning)
143
144 RadioAction = override(RadioAction)
145 __all__.append("RadioAction")
146
147
148 class ActionGroup(Gtk.ActionGroup):
149     __init__ = deprecated_init(Gtk.ActionGroup.__init__,
150                                arg_names=('name',),
151                                category=PyGTKDeprecationWarning)
152
153     def add_actions(self, entries, user_data=None):
154         """
155         The add_actions() method is a convenience method that creates a number
156         of gtk.Action  objects based on the information in the list of action
157         entry tuples contained in entries and adds them to the action group.
158         The entry tuples can vary in size from one to six items with the
159         following information:
160
161             * The name of the action. Must be specified.
162             * The stock id for the action. Optional with a default value of None
163               if a label is specified.
164             * The label for the action. This field should typically be marked
165               for translation, see the set_translation_domain() method. Optional
166               with a default value of None if a stock id is specified.
167             * The accelerator for the action, in the format understood by the
168               gtk.accelerator_parse() function. Optional with a default value of
169               None.
170             * The tooltip for the action. This field should typically be marked
171               for translation, see the set_translation_domain() method. Optional
172               with a default value of None.
173             * The callback function invoked when the action is activated.
174               Optional with a default value of None.
175
176         The "activate" signals of the actions are connected to the callbacks and
177         their accel paths are set to <Actions>/group-name/action-name.
178         """
179         try:
180             iter(entries)
181         except (TypeError):
182             raise TypeError('entries must be iterable')
183
184         def _process_action(name, stock_id=None, label=None, accelerator=None, tooltip=None, callback=None):
185             action = Action(name=name, label=label, tooltip=tooltip, stock_id=stock_id)
186             if callback is not None:
187                 if user_data is None:
188                     action.connect('activate', callback)
189                 else:
190                     action.connect('activate', callback, user_data)
191
192             self.add_action_with_accel(action, accelerator)
193
194         for e in entries:
195             # using inner function above since entries can leave out optional arguments
196             _process_action(*e)
197
198     def add_toggle_actions(self, entries, user_data=None):
199         """
200         The add_toggle_actions() method is a convenience method that creates a
201         number of gtk.ToggleAction objects based on the information in the list
202         of action entry tuples contained in entries and adds them to the action
203         group. The toggle action entry tuples can vary in size from one to seven
204         items with the following information:
205
206             * The name of the action. Must be specified.
207             * The stock id for the action. Optional with a default value of None
208               if a label is specified.
209             * The label for the action. This field should typically be marked
210               for translation, see the set_translation_domain() method. Optional
211               with a default value of None if a stock id is specified.
212             * The accelerator for the action, in the format understood by the
213               gtk.accelerator_parse() function. Optional with a default value of
214               None.
215             * The tooltip for the action. This field should typically be marked
216               for translation, see the set_translation_domain() method. Optional
217               with a default value of None.
218             * The callback function invoked when the action is activated.
219               Optional with a default value of None.
220             * A flag indicating whether the toggle action is active. Optional
221               with a default value of False.
222
223         The "activate" signals of the actions are connected to the callbacks and
224         their accel paths are set to <Actions>/group-name/action-name.
225         """
226
227         try:
228             iter(entries)
229         except (TypeError):
230             raise TypeError('entries must be iterable')
231
232         def _process_action(name, stock_id=None, label=None, accelerator=None, tooltip=None, callback=None, is_active=False):
233             action = Gtk.ToggleAction(name=name, label=label, tooltip=tooltip, stock_id=stock_id)
234             action.set_active(is_active)
235             if callback is not None:
236                 if user_data is None:
237                     action.connect('activate', callback)
238                 else:
239                     action.connect('activate', callback, user_data)
240
241             self.add_action_with_accel(action, accelerator)
242
243         for e in entries:
244             # using inner function above since entries can leave out optional arguments
245             _process_action(*e)
246
247     def add_radio_actions(self, entries, value=None, on_change=None, user_data=None):
248         """
249         The add_radio_actions() method is a convenience method that creates a
250         number of gtk.RadioAction objects based on the information in the list
251         of action entry tuples contained in entries and adds them to the action
252         group. The entry tuples can vary in size from one to six items with the
253         following information:
254
255             * The name of the action. Must be specified.
256             * The stock id for the action. Optional with a default value of None
257               if a label is specified.
258             * The label for the action. This field should typically be marked
259               for translation, see the set_translation_domain() method. Optional
260               with a default value of None if a stock id is specified.
261             * The accelerator for the action, in the format understood by the
262               gtk.accelerator_parse() function. Optional with a default value of
263               None.
264             * The tooltip for the action. This field should typically be marked
265               for translation, see the set_translation_domain() method. Optional
266               with a default value of None.
267             * The value to set on the radio action. Optional with a default
268               value of 0. Should be specified in applications.
269
270         The value parameter specifies the radio action that should be set
271         active. The "changed" signal of the first radio action is connected to
272         the on_change callback (if specified and not None) and the accel paths
273         of the actions are set to <Actions>/group-name/action-name.
274         """
275         try:
276             iter(entries)
277         except (TypeError):
278             raise TypeError('entries must be iterable')
279
280         first_action = None
281
282         def _process_action(group_source, name, stock_id=None, label=None, accelerator=None, tooltip=None, entry_value=0):
283             action = RadioAction(name=name, label=label, tooltip=tooltip, stock_id=stock_id, value=entry_value)
284
285             # FIXME: join_group is a patch to Gtk+ 3.0
286             #        otherwise we can't effectively add radio actions to a
287             #        group.  Should we depend on 3.0 and error out here
288             #        or should we offer the functionality via a compat
289             #        C module?
290             if hasattr(action, 'join_group'):
291                 action.join_group(group_source)
292
293             if value == entry_value:
294                 action.set_active(True)
295
296             self.add_action_with_accel(action, accelerator)
297             return action
298
299         for e in entries:
300             # using inner function above since entries can leave out optional arguments
301             action = _process_action(first_action, *e)
302             if first_action is None:
303                 first_action = action
304
305         if first_action is not None and on_change is not None:
306             if user_data is None:
307                 first_action.connect('changed', on_change)
308             else:
309                 first_action.connect('changed', on_change, user_data)
310
311 ActionGroup = override(ActionGroup)
312 __all__.append('ActionGroup')
313
314
315 class UIManager(Gtk.UIManager):
316     def add_ui_from_string(self, buffer):
317         if not isinstance(buffer, _basestring):
318             raise TypeError('buffer must be a string')
319
320         length = len(buffer.encode('UTF-8'))
321
322         return Gtk.UIManager.add_ui_from_string(self, buffer, length)
323
324     def insert_action_group(self, buffer, length=-1):
325         return Gtk.UIManager.insert_action_group(self, buffer, length)
326
327 UIManager = override(UIManager)
328 __all__.append('UIManager')
329
330
331 class ComboBox(Gtk.ComboBox, Container):
332     get_active_iter = strip_boolean_result(Gtk.ComboBox.get_active_iter)
333
334 ComboBox = override(ComboBox)
335 __all__.append('ComboBox')
336
337
338 class Box(Gtk.Box):
339     __init__ = deprecated_init(Gtk.Box.__init__,
340                                arg_names=('homogeneous', 'spacing'),
341                                category=PyGTKDeprecationWarning)
342
343 Box = override(Box)
344 __all__.append('Box')
345
346
347 class SizeGroup(Gtk.SizeGroup):
348     __init__ = deprecated_init(Gtk.SizeGroup.__init__,
349                                arg_names=('mode',),
350                                deprecated_defaults={'mode': Gtk.SizeGroupMode.VERTICAL},
351                                category=PyGTKDeprecationWarning)
352
353 SizeGroup = override(SizeGroup)
354 __all__.append('SizeGroup')
355
356
357 class MenuItem(Gtk.MenuItem):
358     __init__ = deprecated_init(Gtk.MenuItem.__init__,
359                                arg_names=('label',),
360                                category=PyGTKDeprecationWarning)
361
362 MenuItem = override(MenuItem)
363 __all__.append('MenuItem')
364
365
366 class Builder(Gtk.Builder):
367     @staticmethod
368     def _extract_handler_and_args(obj_or_map, handler_name):
369         handler = None
370         if isinstance(obj_or_map, collections.Mapping):
371             handler = obj_or_map.get(handler_name, None)
372         else:
373             handler = getattr(obj_or_map, handler_name, None)
374
375         if handler is None:
376             raise AttributeError('Handler %s not found' % handler_name)
377
378         args = ()
379         if isinstance(handler, collections.Sequence):
380             if len(handler) == 0:
381                 raise TypeError("Handler %s tuple can not be empty" % handler)
382             args = handler[1:]
383             handler = handler[0]
384
385         elif not _callable(handler):
386             raise TypeError('Handler %s is not a method, function or tuple' % handler)
387
388         return handler, args
389
390     def connect_signals(self, obj_or_map):
391         """Connect signals specified by this builder to a name, handler mapping.
392
393         Connect signal, name, and handler sets specified in the builder with
394         the given mapping "obj_or_map". The handler/value aspect of the mapping
395         can also contain a tuple in the form of (handler [,arg1 [,argN]])
396         allowing for extra arguments to be passed to the handler. For example:
397
398         .. code-block:: python
399
400             builder.connect_signals({'on_clicked': (on_clicked, arg1, arg2)})
401         """
402         def _full_callback(builder, gobj, signal_name, handler_name, connect_obj, flags, obj_or_map):
403             handler, args = self._extract_handler_and_args(obj_or_map, handler_name)
404
405             after = flags & GObject.ConnectFlags.AFTER
406             if connect_obj is not None:
407                 if after:
408                     gobj.connect_object_after(signal_name, handler, connect_obj, *args)
409                 else:
410                     gobj.connect_object(signal_name, handler, connect_obj, *args)
411             else:
412                 if after:
413                     gobj.connect_after(signal_name, handler, *args)
414                 else:
415                     gobj.connect(signal_name, handler, *args)
416
417         self.connect_signals_full(_full_callback, obj_or_map)
418
419     def add_from_string(self, buffer):
420         if not isinstance(buffer, _basestring):
421             raise TypeError('buffer must be a string')
422
423         length = len(buffer)
424
425         return Gtk.Builder.add_from_string(self, buffer, length)
426
427     def add_objects_from_string(self, buffer, object_ids):
428         if not isinstance(buffer, _basestring):
429             raise TypeError('buffer must be a string')
430
431         length = len(buffer)
432
433         return Gtk.Builder.add_objects_from_string(self, buffer, length, object_ids)
434
435 Builder = override(Builder)
436 __all__.append('Builder')
437
438
439 # NOTE: This must come before any other Window/Dialog subclassing, to ensure
440 # that we have a correct inheritance hierarchy.
441
442
443 class Window(Gtk.Window):
444     __init__ = deprecated_init(Gtk.Window.__init__,
445                                arg_names=('type',),
446                                category=PyGTKDeprecationWarning)
447
448 Window = override(Window)
449 __all__.append('Window')
450
451
452 class Dialog(Gtk.Dialog, Container):
453     _old_arg_names = ('title', 'parent', 'flags', 'buttons', '_buttons_property')
454     _init = deprecated_init(Gtk.Dialog.__init__,
455                             arg_names=('title', 'transient_for', 'flags',
456                                        'add_buttons', 'buttons'),
457                             ignore=('flags', 'add_buttons'),
458                             deprecated_aliases={'transient_for': 'parent',
459                                                 'buttons': '_buttons_property'},
460                             category=PyGTKDeprecationWarning)
461
462     def __init__(self, *args, **kwargs):
463
464         new_kwargs = kwargs.copy()
465         old_kwargs = dict(zip(self._old_arg_names, args))
466         old_kwargs.update(kwargs)
467
468         # Increment the warning stacklevel for sub-classes which implement their own __init__.
469         stacklevel = 2
470         if self.__class__ != Dialog and self.__class__.__init__ != Dialog.__init__:
471             stacklevel += 1
472
473         # buttons was overloaded by PyGtk but is needed for Gtk.MessageDialog
474         # as a pass through, so type check the argument and give a deprecation
475         # when it is not of type Gtk.ButtonsType
476         add_buttons = old_kwargs.get('buttons', None)
477         if add_buttons is not None and not isinstance(add_buttons, Gtk.ButtonsType):
478             warnings.warn('The "buttons" argument must be a Gtk.ButtonsType enum value. '
479                           'Please use the "add_buttons" method for adding buttons. '
480                           'See: https://wiki.gnome.org/PyGObject/InitializerDeprecations',
481                           PyGTKDeprecationWarning, stacklevel=stacklevel)
482             if 'buttons' in new_kwargs:
483                 del new_kwargs['buttons']
484         else:
485             add_buttons = None
486
487         flags = old_kwargs.get('flags', 0)
488         if flags:
489             warnings.warn('The "flags" argument for dialog construction is deprecated. '
490                           'Please use initializer keywords: modal=True and/or destroy_with_parent=True. '
491                           'See: https://wiki.gnome.org/PyGObject/InitializerDeprecations',
492                           PyGTKDeprecationWarning, stacklevel=stacklevel)
493
494             if flags & Gtk.DialogFlags.MODAL:
495                 new_kwargs['modal'] = True
496
497             if flags & Gtk.DialogFlags.DESTROY_WITH_PARENT:
498                 new_kwargs['destroy_with_parent'] = True
499
500         self._init(*args, **new_kwargs)
501
502         if add_buttons:
503             self.add_buttons(*add_buttons)
504
505     action_area = property(lambda dialog: dialog.get_action_area())
506     vbox = property(lambda dialog: dialog.get_content_area())
507
508     def add_buttons(self, *args):
509         """
510         The add_buttons() method adds several buttons to the Gtk.Dialog using
511         the button data passed as arguments to the method. This method is the
512         same as calling the Gtk.Dialog.add_button() repeatedly. The button data
513         pairs - button text (or stock ID) and a response ID integer are passed
514         individually. For example:
515
516         .. code-block:: python
517
518             dialog.add_buttons(Gtk.STOCK_OPEN, 42, "Close", Gtk.ResponseType.CLOSE)
519
520         will add "Open" and "Close" buttons to dialog.
521         """
522         def _button(b):
523             while b:
524                 t, r = b[0:2]
525                 b = b[2:]
526                 yield t, r
527
528         try:
529             for text, response in _button(args):
530                 self.add_button(text, response)
531         except (IndexError):
532             raise TypeError('Must pass an even number of arguments')
533
534 Dialog = override(Dialog)
535 __all__.append('Dialog')
536
537
538 class MessageDialog(Gtk.MessageDialog, Dialog):
539     __init__ = deprecated_init(Gtk.MessageDialog.__init__,
540                                arg_names=('parent', 'flags', 'message_type',
541                                           'buttons', 'message_format'),
542                                deprecated_aliases={'text': 'message_format',
543                                                    'message_type': 'type'},
544                                category=PyGTKDeprecationWarning)
545
546     def format_secondary_text(self, message_format):
547         self.set_property('secondary-use-markup', False)
548         self.set_property('secondary-text', message_format)
549
550     def format_secondary_markup(self, message_format):
551         self.set_property('secondary-use-markup', True)
552         self.set_property('secondary-text', message_format)
553
554 MessageDialog = override(MessageDialog)
555 __all__.append('MessageDialog')
556
557
558 class ColorSelectionDialog(Gtk.ColorSelectionDialog):
559     __init__ = deprecated_init(Gtk.ColorSelectionDialog.__init__,
560                                arg_names=('title',),
561                                category=PyGTKDeprecationWarning)
562
563 ColorSelectionDialog = override(ColorSelectionDialog)
564 __all__.append('ColorSelectionDialog')
565
566
567 class FileChooserDialog(Gtk.FileChooserDialog):
568     __init__ = deprecated_init(Gtk.FileChooserDialog.__init__,
569                                arg_names=('title', 'parent', 'action', 'buttons'),
570                                category=PyGTKDeprecationWarning)
571
572 FileChooserDialog = override(FileChooserDialog)
573 __all__.append('FileChooserDialog')
574
575
576 class FontSelectionDialog(Gtk.FontSelectionDialog):
577     __init__ = deprecated_init(Gtk.FontSelectionDialog.__init__,
578                                arg_names=('title',),
579                                category=PyGTKDeprecationWarning)
580
581 FontSelectionDialog = override(FontSelectionDialog)
582 __all__.append('FontSelectionDialog')
583
584
585 class RecentChooserDialog(Gtk.RecentChooserDialog):
586     # Note, the "manager" keyword must work across the entire 3.x series because
587     # "recent_manager" is not backwards compatible with PyGObject versions prior to 3.10.
588     __init__ = deprecated_init(Gtk.RecentChooserDialog.__init__,
589                                arg_names=('title', 'parent', 'recent_manager', 'buttons'),
590                                deprecated_aliases={'recent_manager': 'manager'},
591                                category=PyGTKDeprecationWarning)
592
593 RecentChooserDialog = override(RecentChooserDialog)
594 __all__.append('RecentChooserDialog')
595
596
597 class IconView(Gtk.IconView):
598     __init__ = deprecated_init(Gtk.IconView.__init__,
599                                arg_names=('model',),
600                                category=PyGTKDeprecationWarning)
601
602     get_item_at_pos = strip_boolean_result(Gtk.IconView.get_item_at_pos)
603     get_visible_range = strip_boolean_result(Gtk.IconView.get_visible_range)
604     get_dest_item_at_pos = strip_boolean_result(Gtk.IconView.get_dest_item_at_pos)
605
606 IconView = override(IconView)
607 __all__.append('IconView')
608
609
610 class ToolButton(Gtk.ToolButton):
611     __init__ = deprecated_init(Gtk.ToolButton.__init__,
612                                arg_names=('stock_id',),
613                                category=PyGTKDeprecationWarning)
614
615 ToolButton = override(ToolButton)
616 __all__.append('ToolButton')
617
618
619 class IMContext(Gtk.IMContext):
620     get_surrounding = strip_boolean_result(Gtk.IMContext.get_surrounding)
621
622 IMContext = override(IMContext)
623 __all__.append('IMContext')
624
625
626 class RecentInfo(Gtk.RecentInfo):
627     get_application_info = strip_boolean_result(Gtk.RecentInfo.get_application_info)
628
629 RecentInfo = override(RecentInfo)
630 __all__.append('RecentInfo')
631
632
633 class TextBuffer(Gtk.TextBuffer):
634     def _get_or_create_tag_table(self):
635         table = self.get_tag_table()
636         if table is None:
637             table = Gtk.TextTagTable()
638             self.set_tag_table(table)
639
640         return table
641
642     def create_tag(self, tag_name=None, **properties):
643         """Creates a tag and adds it to the tag table of the TextBuffer.
644
645         :param str tag_name:
646             Name of the new tag, or None
647         :param **properties:
648             Keyword list of properties and their values
649
650         This is equivalent to creating a Gtk.TextTag and then adding the
651         tag to the buffer's tag table. The returned tag is owned by
652         the buffer's tag table.
653
654         If ``tag_name`` is None, the tag is anonymous.
655
656         If ``tag_name`` is not None, a tag called ``tag_name`` must not already
657         exist in the tag table for this buffer.
658
659         Properties are passed as a keyword list of names and values (e.g.
660         foreground='DodgerBlue', weight=Pango.Weight.BOLD)
661
662         :returns:
663             A new tag.
664         """
665
666         tag = Gtk.TextTag(name=tag_name, **properties)
667         self._get_or_create_tag_table().add(tag)
668         return tag
669
670     def create_mark(self, mark_name, where, left_gravity=False):
671         return Gtk.TextBuffer.create_mark(self, mark_name, where, left_gravity)
672
673     def set_text(self, text, length=-1):
674         Gtk.TextBuffer.set_text(self, text, length)
675
676     def insert(self, iter, text, length=-1):
677         if not isinstance(text, _basestring):
678             raise TypeError('text must be a string, not %s' % type(text))
679
680         Gtk.TextBuffer.insert(self, iter, text, length)
681
682     def insert_with_tags(self, iter, text, *tags):
683         start_offset = iter.get_offset()
684         self.insert(iter, text)
685
686         if not tags:
687             return
688
689         start = self.get_iter_at_offset(start_offset)
690
691         for tag in tags:
692             self.apply_tag(tag, start, iter)
693
694     def insert_with_tags_by_name(self, iter, text, *tags):
695         if not tags:
696             return
697
698         tag_objs = []
699
700         for tag in tags:
701             tag_obj = self.get_tag_table().lookup(tag)
702             if not tag_obj:
703                 raise ValueError('unknown text tag: %s' % tag)
704             tag_objs.append(tag_obj)
705
706         self.insert_with_tags(iter, text, *tag_objs)
707
708     def insert_at_cursor(self, text, length=-1):
709         if not isinstance(text, _basestring):
710             raise TypeError('text must be a string, not %s' % type(text))
711
712         Gtk.TextBuffer.insert_at_cursor(self, text, length)
713
714     get_selection_bounds = strip_boolean_result(Gtk.TextBuffer.get_selection_bounds, fail_ret=())
715
716 TextBuffer = override(TextBuffer)
717 __all__.append('TextBuffer')
718
719
720 class TextIter(Gtk.TextIter):
721     forward_search = strip_boolean_result(Gtk.TextIter.forward_search)
722     backward_search = strip_boolean_result(Gtk.TextIter.backward_search)
723
724 TextIter = override(TextIter)
725 __all__.append('TextIter')
726
727
728 class TreeModel(Gtk.TreeModel):
729     def __len__(self):
730         return self.iter_n_children(None)
731
732     def __bool__(self):
733         return True
734
735     # alias for Python 2.x object protocol
736     __nonzero__ = __bool__
737
738     def _getiter(self, key):
739         if isinstance(key, Gtk.TreeIter):
740             return key
741         elif isinstance(key, int) and key < 0:
742             index = len(self) + key
743             if index < 0:
744                 raise IndexError("row index is out of bounds: %d" % key)
745             try:
746                 aiter = self.get_iter(index)
747             except ValueError:
748                 raise IndexError("could not find tree path '%s'" % key)
749             return aiter
750         else:
751             try:
752                 aiter = self.get_iter(key)
753             except ValueError:
754                 raise IndexError("could not find tree path '%s'" % key)
755             return aiter
756
757     def _coerce_path(self, path):
758         if isinstance(path, Gtk.TreePath):
759             return path
760         else:
761             return TreePath(path)
762
763     def __getitem__(self, key):
764         aiter = self._getiter(key)
765         return TreeModelRow(self, aiter)
766
767     def __setitem__(self, key, value):
768         row = self[key]
769         self.set_row(row.iter, value)
770
771     def __delitem__(self, key):
772         aiter = self._getiter(key)
773         self.remove(aiter)
774
775     def __iter__(self):
776         return TreeModelRowIter(self, self.get_iter_first())
777
778     get_iter_first = strip_boolean_result(Gtk.TreeModel.get_iter_first)
779     iter_children = strip_boolean_result(Gtk.TreeModel.iter_children)
780     iter_nth_child = strip_boolean_result(Gtk.TreeModel.iter_nth_child)
781     iter_parent = strip_boolean_result(Gtk.TreeModel.iter_parent)
782     get_iter_from_string = strip_boolean_result(Gtk.TreeModel.get_iter_from_string,
783                                                 ValueError, 'invalid tree path')
784
785     def get_iter(self, path):
786         path = self._coerce_path(path)
787         success, aiter = super(TreeModel, self).get_iter(path)
788         if not success:
789             raise ValueError("invalid tree path '%s'" % path)
790         return aiter
791
792     def iter_next(self, aiter):
793         next_iter = aiter.copy()
794         success = super(TreeModel, self).iter_next(next_iter)
795         if success:
796             return next_iter
797
798     def iter_previous(self, aiter):
799         prev_iter = aiter.copy()
800         success = super(TreeModel, self).iter_previous(prev_iter)
801         if success:
802             return prev_iter
803
804     def _convert_row(self, row):
805         # TODO: Accept a dictionary for row
806         # model.append(None,{COLUMN_ICON: icon, COLUMN_NAME: name})
807         if isinstance(row, str):
808             raise TypeError('Expected a list or tuple, but got str')
809
810         n_columns = self.get_n_columns()
811         if len(row) != n_columns:
812             raise ValueError('row sequence has the incorrect number of elements')
813
814         result = []
815         columns = []
816         for cur_col, value in enumerate(row):
817             # do not try to set None values, they are causing warnings
818             if value is None:
819                 continue
820             result.append(self._convert_value(cur_col, value))
821             columns.append(cur_col)
822         return (result, columns)
823
824     def set_row(self, treeiter, row):
825         converted_row, columns = self._convert_row(row)
826         for column in columns:
827             value = row[column]
828             if value is None:
829                 continue  # None means skip this row
830
831             self.set_value(treeiter, column, value)
832
833     def _convert_value(self, column, value):
834         '''Convert value to a GObject.Value of the expected type'''
835
836         if isinstance(value, GObject.Value):
837             return value
838         return GObject.Value(self.get_column_type(column), value)
839
840     def get(self, treeiter, *columns):
841         n_columns = self.get_n_columns()
842
843         values = []
844         for col in columns:
845             if not isinstance(col, int):
846                 raise TypeError("column numbers must be ints")
847
848             if col < 0 or col >= n_columns:
849                 raise ValueError("column number is out of range")
850
851             values.append(self.get_value(treeiter, col))
852
853         return tuple(values)
854
855     #
856     # Signals supporting python iterables as tree paths
857     #
858     def row_changed(self, path, iter):
859         return super(TreeModel, self).row_changed(self._coerce_path(path), iter)
860
861     def row_inserted(self, path, iter):
862         return super(TreeModel, self).row_inserted(self._coerce_path(path), iter)
863
864     def row_has_child_toggled(self, path, iter):
865         return super(TreeModel, self).row_has_child_toggled(self._coerce_path(path),
866                                                             iter)
867
868     def row_deleted(self, path):
869         return super(TreeModel, self).row_deleted(self._coerce_path(path))
870
871     def rows_reordered(self, path, iter, new_order):
872         return super(TreeModel, self).rows_reordered(self._coerce_path(path),
873                                                      iter, new_order)
874
875
876 TreeModel = override(TreeModel)
877 __all__.append('TreeModel')
878
879
880 class TreeSortable(Gtk.TreeSortable, ):
881
882     get_sort_column_id = strip_boolean_result(Gtk.TreeSortable.get_sort_column_id, fail_ret=(None, None))
883
884     def set_sort_func(self, sort_column_id, sort_func, user_data=None):
885         super(TreeSortable, self).set_sort_func(sort_column_id, sort_func, user_data)
886
887     def set_default_sort_func(self, sort_func, user_data=None):
888         super(TreeSortable, self).set_default_sort_func(sort_func, user_data)
889
890 TreeSortable = override(TreeSortable)
891 __all__.append('TreeSortable')
892
893
894 class TreeModelSort(Gtk.TreeModelSort):
895     __init__ = deprecated_init(Gtk.TreeModelSort.__init__,
896                                arg_names=('model',),
897                                category=PyGTKDeprecationWarning)
898
899 TreeModelSort = override(TreeModelSort)
900 __all__.append('TreeModelSort')
901
902
903 class ListStore(Gtk.ListStore, TreeModel, TreeSortable):
904     def __init__(self, *column_types):
905         Gtk.ListStore.__init__(self)
906         self.set_column_types(column_types)
907
908     def _do_insert(self, position, row):
909         if row is not None:
910             row, columns = self._convert_row(row)
911             treeiter = self.insert_with_valuesv(position, columns, row)
912         else:
913             treeiter = Gtk.ListStore.insert(self, position)
914
915         return treeiter
916
917     def append(self, row=None):
918         if row:
919             return self._do_insert(-1, row)
920         # gtk_list_store_insert() does not know about the "position == -1"
921         # case, so use append() here
922         else:
923             return Gtk.ListStore.append(self)
924
925     def prepend(self, row=None):
926         return self._do_insert(0, row)
927
928     def insert(self, position, row=None):
929         return self._do_insert(position, row)
930
931     # FIXME: sends two signals; check if this can use an atomic
932     # insert_with_valuesv()
933
934     def insert_before(self, sibling, row=None):
935         treeiter = Gtk.ListStore.insert_before(self, sibling)
936
937         if row is not None:
938             self.set_row(treeiter, row)
939
940         return treeiter
941
942     # FIXME: sends two signals; check if this can use an atomic
943     # insert_with_valuesv()
944
945     def insert_after(self, sibling, row=None):
946         treeiter = Gtk.ListStore.insert_after(self, sibling)
947
948         if row is not None:
949             self.set_row(treeiter, row)
950
951         return treeiter
952
953     def set_value(self, treeiter, column, value):
954         value = self._convert_value(column, value)
955         Gtk.ListStore.set_value(self, treeiter, column, value)
956
957     def set(self, treeiter, *args):
958
959         def _set_lists(columns, values):
960             if len(columns) != len(values):
961                 raise TypeError('The number of columns do not match the number of values')
962             for col_num, val in zip(columns, values):
963                 if not isinstance(col_num, int):
964                     raise TypeError('TypeError: Expected integer argument for column.')
965                 self.set_value(treeiter, col_num, val)
966
967         if args:
968             if isinstance(args[0], int):
969                 columns = args[::2]
970                 values = args[1::2]
971                 _set_lists(columns, values)
972             elif isinstance(args[0], (tuple, list)):
973                 if len(args) != 2:
974                     raise TypeError('Too many arguments')
975                 _set_lists(args[0], args[1])
976             elif isinstance(args[0], dict):
977                 columns = args[0].keys()
978                 values = args[0].values()
979                 _set_lists(columns, values)
980             else:
981                 raise TypeError('Argument list must be in the form of (column, value, ...), ((columns,...), (values, ...)) or {column: value}.  No -1 termination is needed.')
982
983 ListStore = override(ListStore)
984 __all__.append('ListStore')
985
986
987 class TreeModelRow(object):
988
989     def __init__(self, model, iter_or_path):
990         if not isinstance(model, Gtk.TreeModel):
991             raise TypeError("expected Gtk.TreeModel, %s found" % type(model).__name__)
992         self.model = model
993         if isinstance(iter_or_path, Gtk.TreePath):
994             self.iter = model.get_iter(iter_or_path)
995         elif isinstance(iter_or_path, Gtk.TreeIter):
996             self.iter = iter_or_path
997         else:
998             raise TypeError("expected Gtk.TreeIter or Gtk.TreePath, \
999                 %s found" % type(iter_or_path).__name__)
1000
1001     @property
1002     def path(self):
1003         return self.model.get_path(self.iter)
1004
1005     @property
1006     def next(self):
1007         return self.get_next()
1008
1009     @property
1010     def previous(self):
1011         return self.get_previous()
1012
1013     @property
1014     def parent(self):
1015         return self.get_parent()
1016
1017     def get_next(self):
1018         next_iter = self.model.iter_next(self.iter)
1019         if next_iter:
1020             return TreeModelRow(self.model, next_iter)
1021
1022     def get_previous(self):
1023         prev_iter = self.model.iter_previous(self.iter)
1024         if prev_iter:
1025             return TreeModelRow(self.model, prev_iter)
1026
1027     def get_parent(self):
1028         parent_iter = self.model.iter_parent(self.iter)
1029         if parent_iter:
1030             return TreeModelRow(self.model, parent_iter)
1031
1032     def __getitem__(self, key):
1033         if isinstance(key, int):
1034             if key >= self.model.get_n_columns():
1035                 raise IndexError("column index is out of bounds: %d" % key)
1036             elif key < 0:
1037                 key = self._convert_negative_index(key)
1038             return self.model.get_value(self.iter, key)
1039         elif isinstance(key, slice):
1040             start, stop, step = key.indices(self.model.get_n_columns())
1041             alist = []
1042             for i in range(start, stop, step):
1043                 alist.append(self.model.get_value(self.iter, i))
1044             return alist
1045         else:
1046             raise TypeError("indices must be integers, not %s" % type(key).__name__)
1047
1048     def __setitem__(self, key, value):
1049         if isinstance(key, int):
1050             if key >= self.model.get_n_columns():
1051                 raise IndexError("column index is out of bounds: %d" % key)
1052             elif key < 0:
1053                 key = self._convert_negative_index(key)
1054             self.model.set_value(self.iter, key, value)
1055         elif isinstance(key, slice):
1056             start, stop, step = key.indices(self.model.get_n_columns())
1057             indexList = range(start, stop, step)
1058             if len(indexList) != len(value):
1059                 raise ValueError(
1060                     "attempt to assign sequence of size %d to slice of size %d"
1061                     % (len(value), len(indexList)))
1062
1063             for i, v in enumerate(indexList):
1064                 self.model.set_value(self.iter, v, value[i])
1065         else:
1066             raise TypeError("index must be an integer or slice, not %s" % type(key).__name__)
1067
1068     def _convert_negative_index(self, index):
1069         new_index = self.model.get_n_columns() + index
1070         if new_index < 0:
1071             raise IndexError("column index is out of bounds: %d" % index)
1072         return new_index
1073
1074     def iterchildren(self):
1075         child_iter = self.model.iter_children(self.iter)
1076         return TreeModelRowIter(self.model, child_iter)
1077
1078 __all__.append('TreeModelRow')
1079
1080
1081 class TreeModelRowIter(object):
1082
1083     def __init__(self, model, aiter):
1084         self.model = model
1085         self.iter = aiter
1086
1087     def __next__(self):
1088         if not self.iter:
1089             raise StopIteration
1090         row = TreeModelRow(self.model, self.iter)
1091         self.iter = self.model.iter_next(self.iter)
1092         return row
1093
1094     # alias for Python 2.x object protocol
1095     next = __next__
1096
1097     def __iter__(self):
1098         return self
1099
1100 __all__.append('TreeModelRowIter')
1101
1102
1103 class TreePath(Gtk.TreePath):
1104
1105     def __new__(cls, path=0):
1106         if isinstance(path, int):
1107             path = str(path)
1108         elif not isinstance(path, _basestring):
1109             path = ":".join(str(val) for val in path)
1110
1111         if len(path) == 0:
1112             raise TypeError("could not parse subscript '%s' as a tree path" % path)
1113         try:
1114             return TreePath.new_from_string(path)
1115         except TypeError:
1116             raise TypeError("could not parse subscript '%s' as a tree path" % path)
1117
1118     def __str__(self):
1119         return self.to_string()
1120
1121     def __lt__(self, other):
1122         return other is not None and self.compare(other) < 0
1123
1124     def __le__(self, other):
1125         return other is not None and self.compare(other) <= 0
1126
1127     def __eq__(self, other):
1128         return other is not None and self.compare(other) == 0
1129
1130     def __ne__(self, other):
1131         return other is None or self.compare(other) != 0
1132
1133     def __gt__(self, other):
1134         return other is None or self.compare(other) > 0
1135
1136     def __ge__(self, other):
1137         return other is None or self.compare(other) >= 0
1138
1139     def __iter__(self):
1140         return iter(self.get_indices())
1141
1142     def __len__(self):
1143         return self.get_depth()
1144
1145     def __getitem__(self, index):
1146         return self.get_indices()[index]
1147
1148 TreePath = override(TreePath)
1149 __all__.append('TreePath')
1150
1151
1152 class TreeStore(Gtk.TreeStore, TreeModel, TreeSortable):
1153     def __init__(self, *column_types):
1154         Gtk.TreeStore.__init__(self)
1155         self.set_column_types(column_types)
1156
1157     def _do_insert(self, parent, position, row):
1158         if row is not None:
1159             row, columns = self._convert_row(row)
1160             treeiter = self.insert_with_values(parent, position, columns, row)
1161         else:
1162             treeiter = Gtk.TreeStore.insert(self, parent, position)
1163
1164         return treeiter
1165
1166     def append(self, parent, row=None):
1167         return self._do_insert(parent, -1, row)
1168
1169     def prepend(self, parent, row=None):
1170         return self._do_insert(parent, 0, row)
1171
1172     def insert(self, parent, position, row=None):
1173         return self._do_insert(parent, position, row)
1174
1175     # FIXME: sends two signals; check if this can use an atomic
1176     # insert_with_valuesv()
1177
1178     def insert_before(self, parent, sibling, row=None):
1179         treeiter = Gtk.TreeStore.insert_before(self, parent, sibling)
1180
1181         if row is not None:
1182             self.set_row(treeiter, row)
1183
1184         return treeiter
1185
1186     # FIXME: sends two signals; check if this can use an atomic
1187     # insert_with_valuesv()
1188
1189     def insert_after(self, parent, sibling, row=None):
1190         treeiter = Gtk.TreeStore.insert_after(self, parent, sibling)
1191
1192         if row is not None:
1193             self.set_row(treeiter, row)
1194
1195         return treeiter
1196
1197     def set_value(self, treeiter, column, value):
1198         value = self._convert_value(column, value)
1199         Gtk.TreeStore.set_value(self, treeiter, column, value)
1200
1201     def set(self, treeiter, *args):
1202
1203         def _set_lists(columns, values):
1204             if len(columns) != len(values):
1205                 raise TypeError('The number of columns do not match the number of values')
1206             for col_num, val in zip(columns, values):
1207                 if not isinstance(col_num, int):
1208                     raise TypeError('TypeError: Expected integer argument for column.')
1209                 self.set_value(treeiter, col_num, val)
1210
1211         if args:
1212             if isinstance(args[0], int):
1213                 columns = args[::2]
1214                 values = args[1::2]
1215                 _set_lists(columns, values)
1216             elif isinstance(args[0], (tuple, list)):
1217                 if len(args) != 2:
1218                     raise TypeError('Too many arguments')
1219                 _set_lists(args[0], args[1])
1220             elif isinstance(args[0], dict):
1221                 columns = args[0].keys()
1222                 values = args[0].values()
1223                 _set_lists(columns, values)
1224             else:
1225                 raise TypeError('Argument list must be in the form of (column, value, ...), ((columns,...), (values, ...)) or {column: value}.  No -1 termination is needed.')
1226
1227 TreeStore = override(TreeStore)
1228 __all__.append('TreeStore')
1229
1230
1231 class TreeView(Gtk.TreeView, Container):
1232     __init__ = deprecated_init(Gtk.TreeView.__init__,
1233                                arg_names=('model',),
1234                                category=PyGTKDeprecationWarning)
1235
1236     get_path_at_pos = strip_boolean_result(Gtk.TreeView.get_path_at_pos)
1237     get_visible_range = strip_boolean_result(Gtk.TreeView.get_visible_range)
1238     get_dest_row_at_pos = strip_boolean_result(Gtk.TreeView.get_dest_row_at_pos)
1239
1240     def enable_model_drag_source(self, start_button_mask, targets, actions):
1241         target_entries = _construct_target_list(targets)
1242         super(TreeView, self).enable_model_drag_source(start_button_mask,
1243                                                        target_entries,
1244                                                        actions)
1245
1246     def enable_model_drag_dest(self, targets, actions):
1247         target_entries = _construct_target_list(targets)
1248         super(TreeView, self).enable_model_drag_dest(target_entries,
1249                                                      actions)
1250
1251     def scroll_to_cell(self, path, column=None, use_align=False, row_align=0.0, col_align=0.0):
1252         if not isinstance(path, Gtk.TreePath):
1253             path = TreePath(path)
1254         super(TreeView, self).scroll_to_cell(path, column, use_align, row_align, col_align)
1255
1256     def set_cursor(self, path, column=None, start_editing=False):
1257         if not isinstance(path, Gtk.TreePath):
1258             path = TreePath(path)
1259         super(TreeView, self).set_cursor(path, column, start_editing)
1260
1261     def get_cell_area(self, path, column=None):
1262         if not isinstance(path, Gtk.TreePath):
1263             path = TreePath(path)
1264         return super(TreeView, self).get_cell_area(path, column)
1265
1266     def insert_column_with_attributes(self, position, title, cell, **kwargs):
1267         column = TreeViewColumn()
1268         column.set_title(title)
1269         column.pack_start(cell, False)
1270         self.insert_column(column, position)
1271         column.set_attributes(cell, **kwargs)
1272
1273 TreeView = override(TreeView)
1274 __all__.append('TreeView')
1275
1276
1277 class TreeViewColumn(Gtk.TreeViewColumn):
1278     def __init__(self, title='',
1279                  cell_renderer=None,
1280                  **attributes):
1281         Gtk.TreeViewColumn.__init__(self, title=title)
1282         if cell_renderer:
1283             self.pack_start(cell_renderer, True)
1284
1285         for (name, value) in attributes.items():
1286             self.add_attribute(cell_renderer, name, value)
1287
1288     cell_get_position = strip_boolean_result(Gtk.TreeViewColumn.cell_get_position)
1289
1290     def set_cell_data_func(self, cell_renderer, func, func_data=None):
1291         super(TreeViewColumn, self).set_cell_data_func(cell_renderer, func, func_data)
1292
1293     def set_attributes(self, cell_renderer, **attributes):
1294         Gtk.CellLayout.clear_attributes(self, cell_renderer)
1295
1296         for (name, value) in attributes.items():
1297             Gtk.CellLayout.add_attribute(self, cell_renderer, name, value)
1298
1299
1300 TreeViewColumn = override(TreeViewColumn)
1301 __all__.append('TreeViewColumn')
1302
1303
1304 class TreeSelection(Gtk.TreeSelection):
1305
1306     def select_path(self, path):
1307         if not isinstance(path, Gtk.TreePath):
1308             path = TreePath(path)
1309         super(TreeSelection, self).select_path(path)
1310
1311     def get_selected(self):
1312         success, model, aiter = super(TreeSelection, self).get_selected()
1313         if success:
1314             return (model, aiter)
1315         else:
1316             return (model, None)
1317
1318     # for compatibility with PyGtk
1319
1320     def get_selected_rows(self):
1321         rows, model = super(TreeSelection, self).get_selected_rows()
1322         return (model, rows)
1323
1324
1325 TreeSelection = override(TreeSelection)
1326 __all__.append('TreeSelection')
1327
1328
1329 class Button(Gtk.Button, Container):
1330     _init = deprecated_init(Gtk.Button.__init__,
1331                             arg_names=('label', 'stock', 'use_stock', 'use_underline'),
1332                             ignore=('stock',),
1333                             category=PyGTKDeprecationWarning,
1334                             stacklevel=3)
1335
1336     def __init__(self, *args, **kwargs):
1337         # Doubly deprecated initializer, the stock keyword is non-standard.
1338         # Simply give a warning that stock items are deprecated even though
1339         # we want to deprecate the non-standard keyword as well here from
1340         # the overrides.
1341         if 'stock' in kwargs and kwargs['stock']:
1342             warnings.warn('Stock items are deprecated. '
1343                           'Please use: Gtk.Button.new_with_mnemonic(label)',
1344                           PyGTKDeprecationWarning, stacklevel=2)
1345             new_kwargs = kwargs.copy()
1346             new_kwargs['label'] = new_kwargs['stock']
1347             new_kwargs['use_stock'] = True
1348             new_kwargs['use_underline'] = True
1349             del new_kwargs['stock']
1350             Gtk.Button.__init__(self, **new_kwargs)
1351         else:
1352             self._init(*args, **kwargs)
1353
1354 Button = override(Button)
1355 __all__.append('Button')
1356
1357
1358 class LinkButton(Gtk.LinkButton):
1359     __init__ = deprecated_init(Gtk.LinkButton.__init__,
1360                                arg_names=('uri', 'label'),
1361                                category=PyGTKDeprecationWarning)
1362
1363 LinkButton = override(LinkButton)
1364 __all__.append('LinkButton')
1365
1366
1367 class Label(Gtk.Label):
1368     __init__ = deprecated_init(Gtk.Label.__init__,
1369                                arg_names=('label',),
1370                                category=PyGTKDeprecationWarning)
1371
1372 Label = override(Label)
1373 __all__.append('Label')
1374
1375
1376 class Adjustment(Gtk.Adjustment):
1377     _init = deprecated_init(Gtk.Adjustment.__init__,
1378                             arg_names=('value', 'lower', 'upper',
1379                                        'step_increment', 'page_increment', 'page_size'),
1380                             deprecated_aliases={'page_increment': 'page_incr',
1381                                                 'step_increment': 'step_incr'},
1382                             category=PyGTKDeprecationWarning,
1383                             stacklevel=3)
1384
1385     def __init__(self, *args, **kwargs):
1386         self._init(*args, **kwargs)
1387
1388         # The value property is set between lower and (upper - page_size).
1389         # Just in case lower, upper or page_size was still 0 when value
1390         # was set, we set it again here.
1391         if 'value' in kwargs:
1392             self.set_value(kwargs['value'])
1393
1394 Adjustment = override(Adjustment)
1395 __all__.append('Adjustment')
1396
1397
1398 class Table(Gtk.Table, Container):
1399     __init__ = deprecated_init(Gtk.Table.__init__,
1400                                arg_names=('n_rows', 'n_columns', 'homogeneous'),
1401                                deprecated_aliases={'n_rows': 'rows', 'n_columns': 'columns'},
1402                                category=PyGTKDeprecationWarning)
1403
1404     def attach(self, child, left_attach, right_attach, top_attach, bottom_attach, xoptions=Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, yoptions=Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, xpadding=0, ypadding=0):
1405         Gtk.Table.attach(self, child, left_attach, right_attach, top_attach, bottom_attach, xoptions, yoptions, xpadding, ypadding)
1406
1407 Table = override(Table)
1408 __all__.append('Table')
1409
1410
1411 class ScrolledWindow(Gtk.ScrolledWindow):
1412     __init__ = deprecated_init(Gtk.ScrolledWindow.__init__,
1413                                arg_names=('hadjustment', 'vadjustment'),
1414                                category=PyGTKDeprecationWarning)
1415
1416 ScrolledWindow = override(ScrolledWindow)
1417 __all__.append('ScrolledWindow')
1418
1419
1420 class HScrollbar(Gtk.HScrollbar):
1421     __init__ = deprecated_init(Gtk.HScrollbar.__init__,
1422                                arg_names=('adjustment',),
1423                                category=PyGTKDeprecationWarning)
1424
1425 HScrollbar = override(HScrollbar)
1426 __all__.append('HScrollbar')
1427
1428
1429 class VScrollbar(Gtk.VScrollbar):
1430     __init__ = deprecated_init(Gtk.VScrollbar.__init__,
1431                                arg_names=('adjustment',),
1432                                category=PyGTKDeprecationWarning)
1433
1434 VScrollbar = override(VScrollbar)
1435 __all__.append('VScrollbar')
1436
1437
1438 class Paned(Gtk.Paned):
1439     def pack1(self, child, resize=False, shrink=True):
1440         super(Paned, self).pack1(child, resize, shrink)
1441
1442     def pack2(self, child, resize=True, shrink=True):
1443         super(Paned, self).pack2(child, resize, shrink)
1444
1445 Paned = override(Paned)
1446 __all__.append('Paned')
1447
1448
1449 class Arrow(Gtk.Arrow):
1450     __init__ = deprecated_init(Gtk.Arrow.__init__,
1451                                arg_names=('arrow_type', 'shadow_type'),
1452                                category=PyGTKDeprecationWarning)
1453
1454 Arrow = override(Arrow)
1455 __all__.append('Arrow')
1456
1457
1458 class IconSet(Gtk.IconSet):
1459     def __new__(cls, pixbuf=None):
1460         if pixbuf is not None:
1461             warnings.warn('Gtk.IconSet(pixbuf) has been deprecated. Please use: '
1462                           'Gtk.IconSet.new_from_pixbuf(pixbuf)',
1463                           PyGTKDeprecationWarning, stacklevel=2)
1464             iconset = Gtk.IconSet.new_from_pixbuf(pixbuf)
1465         else:
1466             iconset = Gtk.IconSet.__new__(cls)
1467         return iconset
1468
1469 IconSet = override(IconSet)
1470 __all__.append('IconSet')
1471
1472
1473 class Viewport(Gtk.Viewport):
1474     __init__ = deprecated_init(Gtk.Viewport.__init__,
1475                                arg_names=('hadjustment', 'vadjustment'),
1476                                category=PyGTKDeprecationWarning)
1477
1478 Viewport = override(Viewport)
1479 __all__.append('Viewport')
1480
1481
1482 class TreeModelFilter(Gtk.TreeModelFilter):
1483     def set_visible_func(self, func, data=None):
1484         super(TreeModelFilter, self).set_visible_func(func, data)
1485
1486     def set_value(self, iter, column, value):
1487         # Delegate to child model
1488         iter = self.convert_iter_to_child_iter(iter)
1489         self.get_model().set_value(iter, column, value)
1490
1491 TreeModelFilter = override(TreeModelFilter)
1492 __all__.append('TreeModelFilter')
1493
1494 if Gtk._version != '2.0':
1495     class Menu(Gtk.Menu):
1496         def popup(self, parent_menu_shell, parent_menu_item, func, data, button, activate_time):
1497             self.popup_for_device(None, parent_menu_shell, parent_menu_item, func, data, button, activate_time)
1498     Menu = override(Menu)
1499     __all__.append('Menu')
1500
1501 _Gtk_main_quit = Gtk.main_quit
1502
1503
1504 @override(Gtk.main_quit)
1505 def main_quit(*args):
1506     _Gtk_main_quit()
1507
1508 stock_lookup = strip_boolean_result(Gtk.stock_lookup)
1509 __all__.append('stock_lookup')
1510
1511 initialized, argv = Gtk.init_check(sys.argv)
1512 sys.argv = list(argv)