1 # -*- Mode: Python; py-indent-offset: 4 -*-
2 # vim: tabstop=4 shiftwidth=4 expandtab
4 # Copyright (C) 2009 Johan Dahlin <johan@gnome.org>
5 # 2010 Simon van der Linden <svdlinden@src.gnome.org>
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.
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.
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
23 from gi import _gobject
24 from gi.repository import GObject
25 from ..overrides import override
26 from ..importer import modules
28 if sys.version_info >= (3, 0):
30 _callable = lambda c: hasattr(c, '__call__')
32 _basestring = basestring
35 Gtk = modules['Gtk']._introspection_module
38 if Gtk._version == '2.0':
40 warn_msg = "You have imported the Gtk 2.0 module. Because Gtk 2.0 \
41 was not designed for use with introspection some of the \
42 interfaces and API will fail. As such this is not supported \
43 by the pygobject development team and we encourage you to \
44 port your app to Gtk 3 or greater. PyGTK is the recomended \
45 python module to use with Gtk 2.0"
47 warnings.warn(warn_msg, RuntimeWarning)
50 class Widget(Gtk.Widget):
52 def translate_coordinates(self, dest_widget, src_x, src_y):
53 success, dest_x, dest_y = super(Widget, self).translate_coordinates(
54 dest_widget, src_x, src_y)
56 return (dest_x, dest_y,)
58 def render_icon(self, stock_id, size, detail=None):
59 return super(Widget, self).render_icon(stock_id, size, detail)
61 Widget = override(Widget)
62 __all__.append('Widget')
64 class Container(Gtk.Container, Widget):
67 return len(self.get_children())
69 def __contains__(self, child):
70 return child in self.get_children()
73 return iter(self.get_children())
78 # alias for Python 2.x object protocol
79 __nonzero__ = __bool__
81 def get_focus_chain(self):
82 success, widgets = super(Container, self).get_focus_chain()
86 Container = override(Container)
87 __all__.append('Container')
89 class Editable(Gtk.Editable):
91 def insert_text(self, text, position):
92 pos = super(Editable, self).insert_text(text, -1, position)
96 def get_selection_bounds(self):
97 success, start_pos, end_pos = super(Editable, self).get_selection_bounds()
99 return (start_pos, end_pos,)
103 Editable = override(Editable)
104 __all__.append("Editable")
106 class Action(Gtk.Action):
107 def __init__(self, name, label, tooltip, stock_id, **kwds):
108 Gtk.Action.__init__(self, name=name, label=label, tooltip=tooltip, stock_id=stock_id, **kwds)
110 Action = override(Action)
111 __all__.append("Action")
113 class RadioAction(Gtk.RadioAction):
114 def __init__(self, name, label, tooltip, stock_id, value, **kwds):
115 Gtk.RadioAction.__init__(self, name=name, label=label, tooltip=tooltip, stock_id=stock_id, value=value, **kwds)
117 RadioAction = override(RadioAction)
118 __all__.append("RadioAction")
120 class ActionGroup(Gtk.ActionGroup):
121 def __init__(self, name, **kwds):
122 super(ActionGroup, self).__init__(name = name, **kwds)
124 def add_actions(self, entries, user_data=None):
126 The add_actions() method is a convenience method that creates a number
127 of gtk.Action objects based on the information in the list of action
128 entry tuples contained in entries and adds them to the action group.
129 The entry tuples can vary in size from one to six items with the
130 following information:
132 * The name of the action. Must be specified.
133 * The stock id for the action. Optional with a default value of None
134 if a label is specified.
135 * The label for the action. This field should typically be marked
136 for translation, see the set_translation_domain() method. Optional
137 with a default value of None if a stock id is specified.
138 * The accelerator for the action, in the format understood by the
139 gtk.accelerator_parse() function. Optional with a default value of
141 * The tooltip for the action. This field should typically be marked
142 for translation, see the set_translation_domain() method. Optional
143 with a default value of None.
144 * The callback function invoked when the action is activated.
145 Optional with a default value of None.
147 The "activate" signals of the actions are connected to the callbacks and
148 their accel paths are set to <Actions>/group-name/action-name.
153 raise TypeError('entries must be iterable')
155 def _process_action(name, stock_id=None, label=None, accelerator=None, tooltip=None, callback=None):
156 action = Action(name, label, tooltip, stock_id)
157 if callback is not None:
158 if user_data is None:
159 action.connect('activate', callback)
161 action.connect('activate', callback, user_data)
163 self.add_action_with_accel(action, accelerator)
166 # using inner function above since entries can leave out optional arguments
169 def add_toggle_actions(self, entries, user_data=None):
171 The add_toggle_actions() method is a convenience method that creates a
172 number of gtk.ToggleAction objects based on the information in the list
173 of action entry tuples contained in entries and adds them to the action
174 group. The toggle action entry tuples can vary in size from one to seven
175 items with the following information:
177 * The name of the action. Must be specified.
178 * The stock id for the action. Optional with a default value of None
179 if a label is specified.
180 * The label for the action. This field should typically be marked
181 for translation, see the set_translation_domain() method. Optional
182 with a default value of None if a stock id is specified.
183 * The accelerator for the action, in the format understood by the
184 gtk.accelerator_parse() function. Optional with a default value of
186 * The tooltip for the action. This field should typically be marked
187 for translation, see the set_translation_domain() method. Optional
188 with a default value of None.
189 * The callback function invoked when the action is activated.
190 Optional with a default value of None.
191 * A flag indicating whether the toggle action is active. Optional
192 with a default value of False.
194 The "activate" signals of the actions are connected to the callbacks and
195 their accel paths are set to <Actions>/group-name/action-name.
201 raise TypeError('entries must be iterable')
203 def _process_action(name, stock_id=None, label=None, accelerator=None, tooltip=None, callback=None, is_active=False):
204 action = Gtk.ToggleAction(name, label, tooltip, stock_id)
205 action.set_active(is_active)
206 if callback is not None:
207 if user_data is None:
208 action.connect('activate', callback)
210 action.connect('activate', callback, user_data)
212 self.add_action_with_accel(action, accelerator)
215 # using inner function above since entries can leave out optional arguments
219 def add_radio_actions(self, entries, value=None, on_change=None, user_data=None):
221 The add_radio_actions() method is a convenience method that creates a
222 number of gtk.RadioAction objects based on the information in the list
223 of action entry tuples contained in entries and adds them to the action
224 group. The entry tuples can vary in size from one to six items with the
225 following information:
227 * The name of the action. Must be specified.
228 * The stock id for the action. Optional with a default value of None
229 if a label is specified.
230 * The label for the action. This field should typically be marked
231 for translation, see the set_translation_domain() method. Optional
232 with a default value of None if a stock id is specified.
233 * The accelerator for the action, in the format understood by the
234 gtk.accelerator_parse() function. Optional with a default value of
236 * The tooltip for the action. This field should typically be marked
237 for translation, see the set_translation_domain() method. Optional
238 with a default value of None.
239 * The value to set on the radio action. Optional with a default
240 value of 0. Should be specified in applications.
242 The value parameter specifies the radio action that should be set
243 active. The "changed" signal of the first radio action is connected to
244 the on_change callback (if specified and not None) and the accel paths
245 of the actions are set to <Actions>/group-name/action-name.
250 raise TypeError('entries must be iterable')
254 def _process_action(group_source, name, stock_id=None, label=None, accelerator=None, tooltip=None, entry_value=0):
255 action = RadioAction(name, label, tooltip, stock_id, entry_value)
257 # FIXME: join_group is a patch to Gtk+ 3.0
258 # otherwise we can't effectively add radio actions to a
259 # group. Should we depend on 3.0 and error out here
260 # or should we offer the functionality via a compat
262 if hasattr(action, 'join_group'):
263 action.join_group(group_source)
265 if value == entry_value:
266 action.set_active(True)
268 self.add_action_with_accel(action, accelerator)
272 # using inner function above since entries can leave out optional arguments
273 action = _process_action(first_action, *e)
274 if first_action is None:
275 first_action = action
277 if first_action is not None and on_change is not None:
278 if user_data is None:
279 action.connect('changed', on_change)
281 action.connect('changed', on_change, user_data)
283 ActionGroup = override(ActionGroup)
284 __all__.append('ActionGroup')
286 class UIManager(Gtk.UIManager):
287 def add_ui_from_string(self, buffer):
288 if not isinstance(buffer, _basestring):
289 raise TypeError('buffer must be a string')
293 return Gtk.UIManager.add_ui_from_string(self, buffer, length)
295 def insert_action_group(self, buffer, length=-1):
296 return Gtk.UIManager.insert_action_group(self, buffer, length)
298 UIManager = override(UIManager)
299 __all__.append('UIManager')
301 class ComboBox(Gtk.ComboBox, Container):
303 def get_active_iter(self):
304 success, aiter = super(ComboBox, self).get_active_iter()
308 ComboBox = override(ComboBox)
309 __all__.append('ComboBox')
313 def __init__(self, homogeneous=False, spacing=0, **kwds):
314 super(Box, self).__init__(**kwds)
315 self.set_homogeneous(homogeneous)
316 self.set_spacing(spacing)
319 __all__.append('Box')
321 class SizeGroup(Gtk.SizeGroup):
322 def __init__(self, mode=Gtk.SizeGroupMode.VERTICAL):
323 super(SizeGroup, self).__init__(mode=mode)
325 SizeGroup = override(SizeGroup)
326 __all__.append('SizeGroup')
329 class MenuItem(Gtk.MenuItem):
330 def __init__(self, label=None):
331 super(MenuItem, self).__init__(label=label)
333 MenuItem = override(MenuItem)
334 __all__.append('MenuItem')
337 class Builder(Gtk.Builder):
339 def connect_signals(self, obj_or_map):
340 def _full_callback(builder, gobj, signal_name, handler_name, connect_obj, flags, obj_or_map):
342 if isinstance(obj_or_map, dict):
343 handler = obj_or_map.get(handler_name, None)
345 handler = getattr(obj_or_map, handler_name, None)
348 raise AttributeError('Handler %s not found' % handler_name)
350 if not _callable(handler):
351 raise TypeError('Handler %s is not a method or function' % handler_name)
353 after = flags or GObject.ConnectFlags.AFTER
354 if connect_obj is not None:
356 gobj.connect_object_after(signal_name, handler, connect_obj)
358 gobj.connect_object(signal_name, handler, connect_obj)
361 gobj.connect_after(signal_name, handler)
363 gobj.connect(signal_name, handler)
365 self.connect_signals_full(_full_callback, obj_or_map)
367 def add_from_string(self, buffer):
368 if not isinstance(buffer, _basestring):
369 raise TypeError('buffer must be a string')
373 return Gtk.Builder.add_from_string(self, buffer, length)
375 def add_objects_from_string(self, buffer, object_ids):
376 if not isinstance(buffer, _basestring):
377 raise TypeError('buffer must be a string')
381 return Gtk.Builder.add_objects_from_string(self, buffer, length, object_ids)
383 Builder = override(Builder)
384 __all__.append('Builder')
387 class Dialog(Gtk.Dialog, Container):
394 _buttons_property=None,
397 # buttons is overloaded by PyGtk so we have to do the same here
398 # this breaks some subclasses of Dialog so add a _buttons_property
399 # keyword to work around this
400 if _buttons_property is not None:
401 kwds['buttons'] = _buttons_property
403 Gtk.Dialog.__init__(self, **kwds)
405 self.set_title(title)
407 self.set_transient_for(parent)
408 if flags & Gtk.DialogFlags.MODAL:
410 if flags & Gtk.DialogFlags.DESTROY_WITH_PARENT:
411 self.set_destroy_with_parent(True)
413 # NO_SEPARATOR has been removed from Gtk 3
415 if flags & Gtk.DialogFlags.NO_SEPARATOR:
416 self.set_has_separator(False)
417 except AttributeError:
419 warnings.warn("Gtk.DialogFlags.NO_SEPARATOR has been depricated since Gtk+-3.0", DeprecationWarning)
421 if buttons is not None:
422 self.add_buttons(*buttons)
424 action_area = property(lambda dialog: dialog.get_action_area())
425 vbox = property(lambda dialog: dialog.get_content_area())
427 def add_buttons(self, *args):
429 The add_buttons() method adds several buttons to the Gtk.Dialog using
430 the button data passed as arguments to the method. This method is the
431 same as calling the Gtk.Dialog.add_button() repeatedly. The button data
432 pairs - button text (or stock ID) and a response ID integer are passed
433 individually. For example:
435 >>> dialog.add_buttons(Gtk.STOCK_OPEN, 42, "Close", Gtk.ResponseType.CLOSE)
437 will add "Open" and "Close" buttons to dialog.
446 for text, response in _button(args):
447 self.add_button(text, response)
449 raise TypeError('Must pass an even number of arguments')
451 Dialog = override(Dialog)
452 __all__.append('Dialog')
454 class MessageDialog(Gtk.MessageDialog, Dialog):
458 message_type=Gtk.MessageType.INFO,
459 buttons=Gtk.ButtonsType.NONE,
463 if message_format != None:
464 kwds['text'] = message_format
466 # type keyword is used for backwards compat with PyGTK
469 warnings.warn("The use of the keyword type as a parameter of the Gtk.MessageDialog constructor has been depricated. Please use message_type instead.", DeprecationWarning)
470 message_type = kwds.pop('type')
472 Gtk.MessageDialog.__init__(self,
473 _buttons_property=buttons,
474 message_type=message_type,
476 Dialog.__init__(self, parent=parent, flags=flags)
478 def format_secondary_text(self, message_format):
479 self.set_property('secondary-use-markup', False)
480 self.set_property('secondary-text', message_format)
482 def format_secondary_markup(self, message_format):
483 self.set_property('secondary-use-markup', True)
484 self.set_property('secondary-text', message_format)
486 MessageDialog = override(MessageDialog)
487 __all__.append('MessageDialog')
489 class AboutDialog(Gtk.AboutDialog, Dialog):
490 def __init__(self, **kwds):
491 Gtk.AboutDialog.__init__(self, **kwds)
492 Dialog.__init__(self)
494 AboutDialog = override(AboutDialog)
495 __all__.append('AboutDialog')
497 class ColorSelectionDialog(Gtk.ColorSelectionDialog, Dialog):
498 def __init__(self, title=None, **kwds):
499 Gtk.ColorSelectionDialog.__init__(self, **kwds)
500 Dialog.__init__(self, title=title)
502 ColorSelectionDialog = override(ColorSelectionDialog)
503 __all__.append('ColorSelectionDialog')
505 class FileChooserDialog(Gtk.FileChooserDialog, Dialog):
509 action=Gtk.FileChooserAction.OPEN,
512 Gtk.FileChooserDialog.__init__(self,
515 Dialog.__init__(self,
520 FileChooserDialog = override(FileChooserDialog)
521 __all__.append('FileChooserDialog')
523 class FontSelectionDialog(Gtk.FontSelectionDialog, Dialog):
524 def __init__(self, title=None, **kwds):
525 Gtk.FontSelectionDialog.__init__(self, **kwds)
526 Dialog.__init__(self, title=title)
528 FontSelectionDialog = override(FontSelectionDialog)
529 __all__.append('FontSelectionDialog')
531 class RecentChooserDialog(Gtk.RecentChooserDialog, Dialog):
539 Gtk.RecentChooserDialog.__init__(self, recent_manager=manager, **kwds)
540 Dialog.__init__(self,
545 RecentChooserDialog = override(RecentChooserDialog)
546 __all__.append('RecentChooserDialog')
548 class IconView(Gtk.IconView):
550 def get_item_at_pos(self, x, y):
551 success, path, cell = super(IconView, self).get_item_at_pos(x, y)
555 def get_visible_range(self):
556 success, start_path, end_path = super(IconView, self).get_visible_range()
558 return (start_path, end_path,)
560 def get_dest_item_at_pos(self, drag_x, drag_y):
561 success, path, pos = super(IconView, self).get_dest_item_at_pos(drag_x, drag_y)
565 IconView = override(IconView)
566 __all__.append('IconView')
568 class IMContext(Gtk.IMContext):
570 def get_surrounding(self):
571 success, text, cursor_index = super(IMContext, self).get_surrounding()
573 return (text, cursor_index,)
575 IMContext = override(IMContext)
576 __all__.append('IMContext')
578 class RecentInfo(Gtk.RecentInfo):
580 def get_application_info(self, app_name):
581 success, app_exec, count, time = super(RecentInfo, self).get_application_info(app_name)
583 return (app_exec, count, time,)
585 RecentInfo = override(RecentInfo)
586 __all__.append('RecentInfo')
588 class TextBuffer(Gtk.TextBuffer):
589 def _get_or_create_tag_table(self):
590 table = self.get_tag_table()
592 table = Gtk.TextTagTable()
593 self.set_tag_table(table)
597 def create_tag(self, tag_name=None, **properties):
599 @tag_name: name of the new tag, or None
600 @properties: keyword list of properties and their values
602 Creates a tag and adds it to the tag table of the TextBuffer.
603 Equivalent to creating a Gtk.TextTag and then adding the
604 tag to the buffer's tag table. The returned tag is owned by
605 the buffer's tag table.
607 If @tag_name is None, the tag is anonymous.
609 If @tag_name is not None, a tag called @tag_name must not already
610 exist in the tag table for this buffer.
612 Properties are passed as a keyword list of names and values (e.g.
613 foreground = 'DodgerBlue', weight = Pango.Weight.BOLD)
615 Return value: a new tag
618 tag = Gtk.TextTag(name=tag_name, **properties)
619 self._get_or_create_tag_table().add(tag)
622 def create_mark(self, mark_name, where, left_gravity=False):
623 return Gtk.TextBuffer.create_mark(self, mark_name, where, left_gravity)
625 def set_text(self, text, length=-1):
626 Gtk.TextBuffer.set_text(self, text, length)
628 def insert(self, iter, text, length=-1):
629 if not isinstance(text , _basestring):
630 raise TypeError('text must be a string, not %s' % type(text))
632 Gtk.TextBuffer.insert(self, iter, text, length)
634 def insert_with_tags(self, iter, text, *tags):
635 start_offset = iter.get_offset()
636 self.insert(iter, text)
641 start = self.get_iter_at_offset(start_offset)
644 self.apply_tag(tag, start, iter)
646 def insert_with_tags_by_name(self, iter, text, *tags):
653 tag_obj = self.get_tag_table().lookup(tag)
655 raise ValueError('unknown text tag: %s' % tag)
656 tag_objs.append(tag_obj)
658 self.insert_with_tags(iter, text, *tag_objs)
660 def insert_at_cursor(self, text, length=-1):
661 if not isinstance(text , _basestring):
662 raise TypeError('text must be a string, not %s' % type(text))
664 Gtk.TextBuffer.insert_at_cursor(self, text, length)
666 def get_selection_bounds(self):
667 success, start, end = super(TextBuffer, self).get_selection_bounds()
673 TextBuffer = override(TextBuffer)
674 __all__.append('TextBuffer')
676 class TextIter(Gtk.TextIter):
678 def forward_search(self, string, flags, limit):
679 success, match_start, match_end = super(TextIter, self).forward_search(string,
682 return (match_start, match_end)
686 def backward_search(self, string, flags, limit):
687 success, match_start, match_end = super(TextIter, self).backward_search(string,
690 return (match_start, match_end)
694 def begins_tag(self, tag=None):
695 return super(TextIter, self).begins_tag(tag)
697 def ends_tag(self, tag=None):
698 return super(TextIter, self).ends_tag(tag)
700 def toggles_tag(self, tag=None):
701 return super(TextIter, self).toggles_tag(tag)
703 TextIter = override(TextIter)
704 __all__.append('TextIter')
706 class TreeModel(Gtk.TreeModel):
708 return self.iter_n_children(None)
713 # alias for Python 2.x object protocol
714 __nonzero__ = __bool__
716 def __getitem__(self, key):
717 if isinstance(key, Gtk.TreeIter):
718 return TreeModelRow(self, key)
719 elif isinstance(key, int) and key < 0:
720 index = len(self) + key
722 raise IndexError("row index is out of bounds: %d" % key)
724 aiter = self.get_iter(index)
726 raise IndexError("could not find tree path '%s'" % key)
727 return TreeModelRow(self, aiter)
730 aiter = self.get_iter(key)
732 raise IndexError("could not find tree path '%s'" % key)
733 return TreeModelRow(self, aiter)
735 def __setitem__(self, key, value):
737 self.set_row(row.iter, value)
740 return TreeModelRowIter(self, self.get_iter_first())
742 def get_iter(self, path):
743 if not isinstance(path, Gtk.TreePath):
744 path = TreePath(path)
746 success, aiter = super(TreeModel, self).get_iter(path)
748 raise ValueError("invalid tree path '%s'" % path)
751 def get_iter_first(self):
752 success, aiter = super(TreeModel, self).get_iter_first()
756 def get_iter_from_string(self, path_string):
757 success, aiter = super(TreeModel, self).get_iter_from_string(path_string)
759 raise ValueError("invalid tree path '%s'" % path_string)
762 def iter_next(self, aiter):
763 next_iter = aiter.copy()
764 success = super(TreeModel, self).iter_next(next_iter)
768 def iter_children(self, aiter):
769 success, child_iter = super(TreeModel, self).iter_children(aiter)
773 def iter_nth_child(self, parent, n):
774 success, child_iter = super(TreeModel, self).iter_nth_child(parent, n)
778 def iter_parent(self, aiter):
779 success, parent_iter = super(TreeModel, self).iter_parent(aiter)
783 def set_row(self, treeiter, row):
784 # TODO: Accept a dictionary for row
785 # model.append(None,{COLUMN_ICON: icon, COLUMN_NAME: name})
786 if isinstance(row, str):
787 raise TypeError('Expected a list or tuple, but got str')
789 n_columns = self.get_n_columns()
790 if len(row) != n_columns:
791 raise ValueError('row sequence has the incorrect number of elements')
793 for i in range(n_columns):
796 continue # None means skip this row
798 self.set_value(treeiter, i, value)
800 def _convert_value(self, treeiter, column, value):
804 # we may need to convert to a basic type
805 type_ = self.get_column_type(column)
806 if type_ == GObject.TYPE_STRING:
807 if isinstance(value, str):
809 elif sys.version_info < (3, 0):
810 if isinstance(value, unicode):
811 value = value.encode('UTF-8')
813 raise ValueError('Expected string or unicode for column %i but got %s%s' % (column, value, type(value)))
815 raise ValueError('Expected a string for column %i but got %s' % (column, type(value)))
816 elif type_ == GObject.TYPE_FLOAT or type_ == GObject.TYPE_DOUBLE:
817 if isinstance(value, float):
820 raise ValueError('Expected a float for column %i but got %s' % (column, type(value)))
821 elif type_ == GObject.TYPE_LONG or type_ == GObject.TYPE_INT:
822 if isinstance(value, int):
824 elif sys.version_info < (3, 0):
825 if isinstance(value, long):
828 raise ValueError('Expected an long for column %i but got %s' % (column, type(value)))
830 raise ValueError('Expected an integer for column %i but got %s' % (column, type(value)))
831 elif type_ == GObject.TYPE_BOOLEAN:
833 if sys.version_info < (3, 0):
834 cmp_classes.append(long)
836 if isinstance(value, tuple(cmp_classes)):
839 raise ValueError('Expected a bool for column %i but got %s' % (column, type(value)))
841 # use GValues directly to marshal to the correct type
842 # standard object checks should take care of validation
843 # so we don't have to do it here
844 value_container = GObject.Value()
845 value_container.init(type_)
846 if type_ == GObject.TYPE_CHAR:
847 value_container.set_char(value)
848 value = value_container
849 elif type_ == GObject.TYPE_UCHAR:
850 value_container.set_uchar(value)
851 value = value_container
852 elif type_ == GObject.TYPE_UNICHAR:
854 if sys.version_info < (3, 0):
855 cmp_classes.append(unicode)
857 if isinstance(value, tuple(cmp_classes)):
858 value = ord(value[0])
860 value_container.set_uint(value)
861 value = value_container
862 elif type_ == GObject.TYPE_UINT:
863 value_container.set_uint(value)
864 value = value_container
865 elif type_ == GObject.TYPE_ULONG:
866 value_container.set_ulong(value)
867 value = value_container
868 elif type_ == GObject.TYPE_INT64:
869 value_container.set_int64(value)
870 value = value_container
871 elif type_ == GObject.TYPE_UINT64:
872 value_container.set_uint64(value)
873 value = value_container
874 elif type_ == GObject.TYPE_PYOBJECT:
875 value_container.set_boxed(value)
876 value = value_container
880 def get(self, treeiter, *columns):
881 n_columns = self.get_n_columns()
885 if not isinstance(col, int):
886 raise TypeError("column numbers must be ints")
888 if col < 0 or col >= n_columns:
889 raise ValueError("column number is out of range")
891 values.append(self.get_value(treeiter, col))
895 def filter_new(self, root=None):
896 return super(TreeModel, self).filter_new(root)
898 TreeModel = override(TreeModel)
899 __all__.append('TreeModel')
901 class TreeSortable(Gtk.TreeSortable, ):
903 def get_sort_column_id(self):
904 success, sort_column_id, order = super(TreeSortable, self).get_sort_column_id()
906 return (sort_column_id, order,)
910 def set_sort_func(self, sort_column_id, sort_func, user_data=None):
911 super(TreeSortable, self).set_sort_func(sort_column_id, sort_func, user_data)
913 def set_default_sort_func(self, sort_func, user_data=None):
914 super(TreeSortable, self).set_default_sort_func(sort_func, user_data)
916 TreeSortable = override(TreeSortable)
917 __all__.append('TreeSortable')
919 class ListStore(Gtk.ListStore, TreeModel, TreeSortable):
920 def __init__(self, *column_types):
921 Gtk.ListStore.__init__(self)
922 self.set_column_types(column_types)
924 def append(self, row=None):
925 treeiter = Gtk.ListStore.append(self)
928 self.set_row(treeiter, row)
932 def insert(self, position, row=None):
933 treeiter = Gtk.ListStore.insert(self, position)
936 self.set_row(treeiter, row)
940 def insert_before(self, sibling, row=None):
941 treeiter = Gtk.ListStore.insert_before(self, sibling)
944 self.set_row(treeiter, row)
948 def insert_after(self, sibling, row=None):
949 treeiter = Gtk.ListStore.insert_after(self, sibling)
952 self.set_row(treeiter, row)
956 def prepend(self, row=None):
957 treeiter = Gtk.ListStore.prepend(self)
960 self.set_row(treeiter, row)
964 def set_value(self, treeiter, column, value):
965 value = self._convert_value(treeiter, column, value)
966 Gtk.ListStore.set_value(self, treeiter, column, value)
968 def set(self, treeiter, *args):
970 def _set_lists(columns, values):
971 if len(columns) != len(values):
972 raise TypeError('The number of columns do not match the number of values')
973 for col_num, val in zip(columns, values):
974 if not isinstance(col_num, int):
975 raise TypeError('TypeError: Expected integer argument for column.')
976 self.set_value(treeiter, col_num, val)
979 if isinstance(args[0], int):
982 _set_lists(columns, values)
983 elif isinstance(args[0], (tuple, list)):
985 raise TypeError('Too many arguments');
986 _set_lists(args[0], args[1])
987 elif isinstance(args[0], dict):
988 columns = args[0].keys()
989 values = args[0].values()
990 _set_lists(columns, values)
992 raise TypeError('Argument list must be in the form of (column, value, ...), ((columns,...), (values, ...)) or {column: value}. No -1 termination is needed.')
994 ListStore = override(ListStore)
995 __all__.append('ListStore')
997 class TreeModelRow(object):
999 def __init__(self, model, iter_or_path):
1000 if not isinstance(model, Gtk.TreeModel):
1001 raise TypeError("expected Gtk.TreeModel, %s found" % type(model).__name__)
1003 if isinstance(iter_or_path, Gtk.TreePath):
1004 self.iter = model.get_iter(iter_or_path)
1005 elif isinstance(iter_or_path, Gtk.TreeIter):
1006 self.iter = iter_or_path
1008 raise TypeError("expected Gtk.TreeIter or Gtk.TreePath, \
1009 %s found" % type(iter_or_path).__name__)
1013 return self.model.get_path(self.iter)
1017 return self.get_next()
1021 return self.get_parent()
1024 next_iter = self.model.iter_next(self.iter)
1026 return TreeModelRow(self.model, next_iter)
1028 def get_parent(self):
1029 parent_iter = self.model.iter_parent(self.iter)
1031 return TreeModelRow(self.model, parent_iter)
1033 def __getitem__(self, key):
1034 if isinstance(key, int):
1035 if key >= self.model.get_n_columns():
1036 raise IndexError("column index is out of bounds: %d" % key)
1038 key = self._convert_negative_index(key)
1039 return self.model.get_value(self.iter, key)
1040 elif isinstance(key, slice):
1041 start, stop, step = key.indices(self.model.get_n_columns())
1043 for i in range(start, stop, step):
1044 alist.append(self.model.get_value(self.iter, i))
1047 raise TypeError("indices must be integers, not %s" % type(key).__name__)
1049 def __setitem__(self, key, value):
1050 if isinstance(key, int):
1051 if key >= self.model.get_n_columns():
1052 raise IndexError("column index is out of bounds: %d" % key)
1054 key = self._convert_negative_index(key)
1055 self.model.set_value(self.iter, key, value)
1056 elif isinstance(key, slice):
1057 start, stop, step = key.indices(self.model.get_n_columns())
1058 indexList = range(start, stop, step)
1059 if len(indexList) != len(value):
1061 "attempt to assign sequence of size %d to slice of size %d"
1062 % (len(value), len(indexList)))
1064 for i,v in enumerate(indexList):
1065 self.model.set_value(self.iter, v, value[i])
1067 raise TypeError("index must be an integer or slice, not %s" % type(key).__name__)
1069 def _convert_negative_index(self, index):
1070 new_index = self.model.get_n_columns() + index
1072 raise IndexError("column index is out of bounds: %d" % index)
1075 def iterchildren(self):
1076 child_iter = self.model.iter_children(self.iter)
1077 return TreeModelRowIter(self.model, child_iter)
1079 __all__.append('TreeModelRow')
1081 class TreeModelRowIter(object):
1083 def __init__(self, model, aiter):
1090 row = TreeModelRow(self.model, self.iter)
1091 self.iter = self.model.iter_next(self.iter)
1094 # alias for Python 2.x object protocol
1100 __all__.append('TreeModelRowIter')
1102 class TreePath(Gtk.TreePath):
1104 def __new__(cls, path=0):
1105 if isinstance(path, int):
1107 elif isinstance(path, tuple):
1108 path = ":".join(str(val) for val in path)
1111 raise TypeError("could not parse subscript '%s' as a tree path" % path)
1113 return TreePath.new_from_string(path)
1115 raise TypeError("could not parse subscript '%s' as a tree path" % path)
1118 return self.to_string()
1120 def __lt__(self, other):
1121 return not other is None and self.compare(other) < 0
1123 def __le__(self, other):
1124 return not other is None and self.compare(other) <= 0
1126 def __eq__(self, other):
1127 return not other is None and self.compare(other) == 0
1129 def __ne__(self, other):
1130 return other is None or self.compare(other) != 0
1132 def __gt__(self, other):
1133 return other is None or self.compare(other) > 0
1135 def __ge__(self, other):
1136 return other is None or self.compare(other) >= 0
1138 TreePath = override(TreePath)
1139 __all__.append('TreePath')
1141 class TreeStore(Gtk.TreeStore, TreeModel, TreeSortable):
1143 def __init__(self, *column_types):
1144 Gtk.TreeStore.__init__(self)
1145 self.set_column_types(column_types)
1147 def append(self, parent, row=None):
1148 treeiter = Gtk.TreeStore.append(self, parent)
1151 self.set_row(treeiter, row)
1155 def insert(self, parent, position, row=None):
1156 treeiter = Gtk.TreeStore.insert(self, parent, position)
1159 self.set_row(treeiter, row)
1163 def insert_before(self, parent, sibling, row=None):
1164 treeiter = Gtk.TreeStore.insert_before(self, parent, sibling)
1167 self.set_row(treeiter, row)
1171 def insert_after(self, parent, sibling, row=None):
1172 treeiter = Gtk.TreeStore.insert_after(self, parent, sibling)
1175 self.set_row(treeiter, row)
1179 def set_value(self, treeiter, column, value):
1180 value = self._convert_value(treeiter, column, value)
1181 Gtk.TreeStore.set_value(self, treeiter, column, value)
1183 def set(self, treeiter, *args):
1185 def _set_lists(columns, values):
1186 if len(columns) != len(values):
1187 raise TypeError('The number of columns do not match the number of values')
1188 for col_num, val in zip(columns, values):
1189 if not isinstance(col_num, int):
1190 raise TypeError('TypeError: Expected integer argument for column.')
1191 self.set_value(treeiter, col_num, val)
1194 if isinstance(args[0], int):
1197 _set_lists(columns, values)
1198 elif isinstance(args[0], (tuple, list)):
1200 raise TypeError('Too many arguments');
1201 _set_lists(args[0], args[1])
1202 elif isinstance(args[0], dict):
1203 columns = args[0].keys()
1204 values = args[0].values()
1205 _set_lists(columns, values)
1207 raise TypeError('Argument list must be in the form of (column, value, ...), ((columns,...), (values, ...)) or {column: value}. No -1 termination is needed.')
1209 TreeStore = override(TreeStore)
1210 __all__.append('TreeStore')
1212 class TreeView(Gtk.TreeView, Container):
1214 def __init__(self, model=None):
1215 Gtk.TreeView.__init__(self)
1217 self.set_model(model)
1219 def get_path_at_pos(self, x, y):
1220 success, path, column, cell_x, cell_y = super(TreeView, self).get_path_at_pos(x, y)
1222 return (path, column, cell_x, cell_y,)
1224 def get_dest_row_at_pos(self, drag_x, drag_y):
1225 success, path, pos = super(TreeView, self).get_dest_row_at_pos(drag_x, drag_y)
1229 def _construct_target_list(self, targets):
1230 # FIXME: this should most likely be part of Widget or a global helper
1234 entry = Gtk.TargetEntry.new(*t)
1235 target_entries.append(entry)
1236 return target_entries
1238 def enable_model_drag_source(self, start_button_mask, targets, actions):
1239 target_entries = self._construct_target_list(targets)
1240 super(TreeView, self).enable_model_drag_source(start_button_mask,
1244 def enable_model_drag_dest(self, targets, actions):
1245 target_entries = self._construct_target_list(targets)
1246 super(TreeView, self).enable_model_drag_dest(target_entries,
1249 def scroll_to_cell(self, path, column=None, use_align=False, row_align=0.0, col_align=0.0):
1250 if not isinstance(path, Gtk.TreePath):
1251 path = TreePath(path)
1252 super(TreeView, self).scroll_to_cell(path, column, use_align, row_align, col_align)
1255 TreeView = override(TreeView)
1256 __all__.append('TreeView')
1258 class TreeViewColumn(Gtk.TreeViewColumn):
1259 def __init__(self, title='',
1262 Gtk.TreeViewColumn.__init__(self, title=title)
1264 self.pack_start(cell_renderer, True)
1266 for (name, value) in attributes.items():
1267 self.add_attribute(cell_renderer, name, value)
1269 def cell_get_position(self, cell_renderer):
1270 success, start_pos, width = super(TreeViewColumn, self).cell_get_position(cell_renderer)
1272 return (start_pos, width,)
1274 def set_cell_data_func(self, cell_renderer, func, func_data=None):
1275 super(TreeViewColumn, self).set_cell_data_func(cell_renderer, func, func_data)
1277 TreeViewColumn = override(TreeViewColumn)
1278 __all__.append('TreeViewColumn')
1280 class TreeSelection(Gtk.TreeSelection):
1282 def select_path(self, path):
1283 if not isinstance(path, Gtk.TreePath):
1284 path = TreePath(path)
1285 super(TreeSelection, self).select_path(path)
1287 def get_selected(self):
1288 success, model, aiter = super(TreeSelection, self).get_selected()
1290 return (model, aiter)
1292 return (model, None)
1294 # for compatibility with PyGtk
1295 def get_selected_rows(self):
1296 rows, model = super(TreeSelection, self).get_selected_rows()
1297 return (model, rows)
1300 TreeSelection = override(TreeSelection)
1301 __all__.append('TreeSelection')
1303 class Button(Gtk.Button, Container):
1304 def __init__(self, label=None, stock=None, use_underline=False, **kwds):
1308 use_underline = True
1311 Gtk.Button.__init__(self, label=label, use_stock=use_stock,
1312 use_underline=use_underline, **kwds)
1313 Button = override(Button)
1314 __all__.append('Button')
1316 class LinkButton(Gtk.LinkButton):
1317 def __init__(self, uri, label=None, **kwds):
1318 Gtk.LinkButton.__init__(self, uri=uri, label=label, **kwds)
1320 LinkButton = override(LinkButton)
1321 __all__.append('LinkButton')
1323 class Label(Gtk.Label):
1324 def __init__(self, label=None, **kwds):
1325 Gtk.Label.__init__(self, label=label, **kwds)
1327 Label = override(Label)
1328 __all__.append('Label')
1330 class Adjustment(Gtk.Adjustment):
1331 def __init__(self, *args, **kwds):
1332 arg_names = ('value', 'lower', 'upper',
1333 'step_increment', 'page_increment', 'page_size')
1334 new_args = dict(zip(arg_names, args))
1335 new_args.update(kwds)
1336 Gtk.Adjustment.__init__(self, **new_args)
1338 # The value property is set between lower and (upper - page_size).
1339 # Just in case lower, upper or page_size was still 0 when value
1340 # was set, we set it again here.
1341 if 'value' in new_args:
1342 self.set_value(new_args['value'])
1344 Adjustment = override(Adjustment)
1345 __all__.append('Adjustment')
1347 class Table(Gtk.Table, Container):
1348 def __init__(self, rows=1, columns=1, homogeneous=False, **kwds):
1349 if 'n_rows' in kwds:
1350 rows = kwds.pop('n_rows')
1352 if 'n_columns' in kwds:
1353 columns = kwds.pop('n_columns')
1355 Gtk.Table.__init__(self, n_rows=rows, n_columns=columns, homogeneous=homogeneous, **kwds)
1357 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):
1358 Gtk.Table.attach(self, child, left_attach, right_attach, top_attach, bottom_attach, xoptions, yoptions, xpadding, ypadding)
1360 Table = override(Table)
1361 __all__.append('Table')
1363 class ScrolledWindow(Gtk.ScrolledWindow):
1364 def __init__(self, hadjustment=None, vadjustment=None, **kwds):
1365 Gtk.ScrolledWindow.__init__(self, hadjustment=hadjustment, vadjustment=vadjustment, **kwds)
1367 ScrolledWindow = override(ScrolledWindow)
1368 __all__.append('ScrolledWindow')
1370 class Paned(Gtk.Paned):
1371 def pack1(self, child, resize=False, shrink=True):
1372 super(Paned, self).pack1(child, resize, shrink)
1374 def pack2(self, child, resize=True, shrink=True):
1375 super(Paned, self).pack2(child, resize, shrink)
1377 Paned = override(Paned)
1378 __all__.append('Paned')
1380 if Gtk._version != '2.0':
1381 class Menu(Gtk.Menu):
1382 def popup(self, parent_menu_shell, parent_menu_item, func, data, button, activate_time):
1383 self.popup_for_device(None, parent_menu_shell, parent_menu_item, func, data, button, activate_time)
1384 Menu = override(Menu)
1385 __all__.append('Menu')
1387 _Gtk_main_quit = Gtk.main_quit
1388 @override(Gtk.main_quit)
1389 def main_quit(*args):
1392 _Gtk_stock_lookup = Gtk.stock_lookup
1393 @override(Gtk.stock_lookup)
1394 def stock_lookup(*args):
1395 success, item = _Gtk_stock_lookup(*args)
1401 initialized, argv = Gtk.init_check(sys.argv)
1402 sys.argv = list(argv)
1404 raise RuntimeError("Gtk couldn't be initialized")