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