Fixed status icon support with GTK 3
[zeroinstall.git] / zeroinstall / gtkui / pygtkcompat.py
blob547f871be8cdcc3c9610d961e96f727c82c4810f
1 # -*- Mode: Python; py-indent-offset: 4 -*-
2 # vim: tabstop=4 shiftwidth=4 expandtab
4 # Copyright (C) 2011-2012 Johan Dahlin <johan@gnome.org>
6 # This library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation; either
9 # version 2.1 of the License, or (at your option) any later version.
11 # This library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # Lesser General Public License for more details.
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with this library; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19 # USA
21 """
22 PyGTK compatibility layer.
24 This modules goes a little bit longer to maintain PyGTK compatibility than
25 the normal overrides system.
27 It is recommended to not depend on this layer, but only use it as an
28 intermediate step when porting your application to PyGI.
30 Compatibility might never be 100%, but the aim is to make it possible to run
31 a well behaved PyGTK application mostly unmodified on top of PyGI.
33 """
35 import sys
36 import warnings
38 try:
39 # Python 3
40 from collections import UserList
41 from imp import reload
42 UserList # pyflakes
43 except ImportError:
44 # Python 2 ships that in a different module
45 from UserList import UserList
46 UserList # pyflakes
48 import gi
49 from gi.repository import GObject
52 def _install_enums(module, dest=None, strip=''):
53 if dest is None:
54 dest = module
55 modname = dest.__name__.rsplit('.', 1)[1].upper()
56 for attr in dir(module):
57 try:
58 obj = getattr(module, attr, None)
59 except:
60 continue
61 try:
62 if issubclass(obj, GObject.GEnum):
63 for value, enum in obj.__enum_values__.items():
64 name = enum.value_name
65 name = name.replace(modname + '_', '')
66 if strip and name.startswith(strip):
67 name = name[len(strip):]
68 setattr(dest, name, enum)
69 except TypeError:
70 continue
71 try:
72 if issubclass(obj, GObject.GFlags):
73 for value, flag in obj.__flags_values__.items():
74 name = flag.value_names[-1].replace(modname + '_', '')
75 setattr(dest, name, flag)
76 except TypeError:
77 continue
80 def enable():
81 # gobject
82 from gi.repository import GLib
83 sys.modules['glib'] = GLib
85 # gobject
86 from gi.repository import GObject
87 sys.modules['gobject'] = GObject
88 #from gi._gobject import propertyhelper
89 #sys.modules['gobject.propertyhelper'] = propertyhelper
91 # gio
92 from gi.repository import Gio
93 sys.modules['gio'] = Gio
95 _unset = object()
98 def enable_gtk(version='2.0'):
99 # set the default encoding like PyGTK
100 reload(sys)
101 if sys.version_info < (3, 0):
102 sys.setdefaultencoding('utf-8')
104 # atk
105 gi.require_version('Atk', '1.0')
106 from gi.repository import Atk
107 sys.modules['atk'] = Atk
108 _install_enums(Atk)
110 # pango
111 gi.require_version('Pango', '1.0')
112 from gi.repository import Pango
113 sys.modules['pango'] = Pango
114 _install_enums(Pango)
116 # pangocairo
117 gi.require_version('PangoCairo', '1.0')
118 from gi.repository import PangoCairo
119 sys.modules['pangocairo'] = PangoCairo
121 # gdk
122 gi.require_version('Gdk', version)
123 gi.require_version('GdkPixbuf', '2.0')
124 from gi.repository import Gdk
125 from gi.repository import GdkPixbuf
126 sys.modules['gtk.gdk'] = Gdk
127 _install_enums(Gdk)
128 _install_enums(GdkPixbuf, dest=Gdk)
129 Gdk._2BUTTON_PRESS = 5
130 Gdk.BUTTON_PRESS = 4
132 Gdk.screen_get_default = Gdk.Screen.get_default
133 Gdk.Pixbuf = GdkPixbuf.Pixbuf
134 Gdk.pixbuf_new_from_file = GdkPixbuf.Pixbuf.new_from_file
135 Gdk.PixbufLoader = GdkPixbuf.PixbufLoader.new_with_type
137 orig_get_formats = GdkPixbuf.Pixbuf.get_formats
139 def get_formats():
140 formats = orig_get_formats()
141 result = []
143 def make_dict(format_):
144 result = {}
145 result['description'] = format_.get_description()
146 result['name'] = format_.get_name()
147 result['mime_types'] = format_.get_mime_types()
148 result['extensions'] = format_.get_extensions()
149 return result
151 for format_ in formats:
152 result.append(make_dict(format_))
153 return result
155 Gdk.pixbuf_get_formats = get_formats
157 orig_get_frame_extents = Gdk.Window.get_frame_extents
159 def get_frame_extents(window):
160 try:
161 try:
162 rect = Gdk.Rectangle(0, 0, 0, 0)
163 except TypeError:
164 rect = Gdk.Rectangle()
165 orig_get_frame_extents(window, rect)
166 except TypeError:
167 rect = orig_get_frame_extents(window)
168 return rect
169 Gdk.Window.get_frame_extents = get_frame_extents
171 orig_get_origin = Gdk.Window.get_origin
173 def get_origin(self):
174 return orig_get_origin(self)[1:]
175 Gdk.Window.get_origin = get_origin
177 Gdk.screen_width = Gdk.Screen.width
178 Gdk.screen_height = Gdk.Screen.height
180 # gtk
181 gi.require_version('Gtk', version)
182 from gi.repository import Gtk
183 sys.modules['gtk'] = Gtk
184 Gtk.gdk = Gdk
186 Gtk.pygtk_version = (2, 99, 0)
188 Gtk.gtk_version = (Gtk.MAJOR_VERSION,
189 Gtk.MINOR_VERSION,
190 Gtk.MICRO_VERSION)
191 _install_enums(Gtk)
193 # Action
195 def set_tool_item_type(menuaction, gtype):
196 warnings.warn('set_tool_item_type() is not supported',
197 DeprecationWarning, stacklevel=2)
198 Gtk.Action.set_tool_item_type = classmethod(set_tool_item_type)
200 # Alignment
202 orig_Alignment = Gtk.Alignment
204 class Alignment(orig_Alignment):
205 def __init__(self, xalign=0.0, yalign=0.0, xscale=0.0, yscale=0.0):
206 orig_Alignment.__init__(self)
207 self.props.xalign = xalign
208 self.props.yalign = yalign
209 self.props.xscale = xscale
210 self.props.yscale = yscale
212 Gtk.Alignment = Alignment
214 # Box
216 orig_pack_end = Gtk.Box.pack_end
218 def pack_end(self, child, expand=True, fill=True, padding=0):
219 orig_pack_end(self, child, expand, fill, padding)
220 Gtk.Box.pack_end = pack_end
222 orig_pack_start = Gtk.Box.pack_start
224 def pack_start(self, child, expand=True, fill=True, padding=0):
225 orig_pack_start(self, child, expand, fill, padding)
226 Gtk.Box.pack_start = pack_start
228 # TreeViewColumn
230 orig_tree_view_column_pack_end = Gtk.TreeViewColumn.pack_end
232 def tree_view_column_pack_end(self, cell, expand=True):
233 orig_tree_view_column_pack_end(self, cell, expand)
234 Gtk.TreeViewColumn.pack_end = tree_view_column_pack_end
236 orig_tree_view_column_pack_start = Gtk.TreeViewColumn.pack_start
238 def tree_view_column_pack_start(self, cell, expand=True):
239 orig_tree_view_column_pack_start(self, cell, expand)
240 Gtk.TreeViewColumn.pack_start = tree_view_column_pack_start
242 # TreeView
244 def insert_column_with_attributes(view, position, title, cell, *args, **kwargs):
245 pass
246 Gtk.TreeView.insert_column_with_attributes = insert_column_with_attributes
248 # CellLayout
250 orig_cell_pack_end = Gtk.CellLayout.pack_end
252 def cell_pack_end(self, cell, expand=True):
253 orig_cell_pack_end(self, cell, expand)
254 Gtk.CellLayout.pack_end = cell_pack_end
256 orig_cell_pack_start = Gtk.CellLayout.pack_start
258 def cell_pack_start(self, cell, expand=True):
259 orig_cell_pack_start(self, cell, expand)
260 Gtk.CellLayout.pack_start = cell_pack_start
262 orig_set_cell_data_func = Gtk.CellLayout.set_cell_data_func
264 def set_cell_data_func(self, cell, func, user_data=_unset):
265 def callback(*args):
266 if args[-1] == _unset:
267 args = args[:-1]
268 return func(*args)
269 orig_set_cell_data_func(self, cell, callback, user_data)
270 Gtk.CellLayout.set_cell_data_func = set_cell_data_func
272 # CellRenderer
274 class GenericCellRenderer(Gtk.CellRenderer):
275 pass
276 Gtk.GenericCellRenderer = GenericCellRenderer
278 # ComboBox
280 orig_combo_row_separator_func = Gtk.ComboBox.set_row_separator_func
282 def combo_row_separator_func(self, func, user_data=_unset):
283 def callback(*args):
284 if args[-1] == _unset:
285 args = args[:-1]
286 return func(*args)
287 orig_combo_row_separator_func(self, callback, user_data)
288 Gtk.ComboBox.set_row_separator_func = combo_row_separator_func
290 # ComboBoxEntry
292 class ComboBoxEntry(Gtk.ComboBox):
293 def __init__(self, **kwds):
294 Gtk.ComboBox.__init__(self, has_entry=True, **kwds)
296 def set_text_column(self, text_column):
297 self.set_entry_text_column(text_column)
299 def get_text_column(self):
300 return self.get_entry_text_column()
301 Gtk.ComboBoxEntry = ComboBoxEntry
303 def combo_box_entry_new():
304 return Gtk.ComboBoxEntry()
305 Gtk.combo_box_entry_new = combo_box_entry_new
307 def combo_box_entry_new_with_model(model):
308 return Gtk.ComboBoxEntry(model=model)
309 Gtk.combo_box_entry_new_with_model = combo_box_entry_new_with_model
311 # Container
313 def install_child_property(container, flag, pspec):
314 warnings.warn('install_child_property() is not supported',
315 DeprecationWarning, stacklevel=2)
316 Gtk.Container.install_child_property = classmethod(install_child_property)
318 def new_text():
319 combo = Gtk.ComboBox()
320 model = Gtk.ListStore(str)
321 combo.set_model(model)
322 combo.set_entry_text_column(0)
323 return combo
324 Gtk.combo_box_new_text = new_text
326 def append_text(self, text):
327 model = self.get_model()
328 model.append([text])
329 Gtk.ComboBox.append_text = append_text
330 Gtk.expander_new_with_mnemonic = Gtk.Expander.new_with_mnemonic
331 Gtk.icon_theme_get_default = Gtk.IconTheme.get_default
332 Gtk.image_new_from_pixbuf = Gtk.Image.new_from_pixbuf
333 Gtk.image_new_from_stock = Gtk.Image.new_from_stock
334 Gtk.image_new_from_animation = Gtk.Image.new_from_animation
335 Gtk.image_new_from_icon_set = Gtk.Image.new_from_icon_set
336 Gtk.image_new_from_file = Gtk.Image.new_from_file
337 Gtk.settings_get_default = Gtk.Settings.get_default
338 Gtk.window_set_default_icon = Gtk.Window.set_default_icon
339 Gtk.clipboard_get = Gtk.Clipboard.get
341 #AccelGroup
342 Gtk.AccelGroup.connect_group = Gtk.AccelGroup.connect
344 #StatusIcon
345 Gtk.status_icon_position_menu = Gtk.StatusIcon.position_menu
346 Gtk.StatusIcon.set_tooltip = Gtk.StatusIcon.set_tooltip_text
348 # Scale
350 orig_HScale = Gtk.HScale
351 orig_VScale = Gtk.VScale
353 class HScale(orig_HScale):
354 def __init__(self, adjustment=None):
355 orig_HScale.__init__(self, adjustment=adjustment)
356 Gtk.HScale = HScale
358 class VScale(orig_VScale):
359 def __init__(self, adjustment=None):
360 orig_VScale.__init__(self, adjustment=adjustment)
361 Gtk.VScale = VScale
363 Gtk.stock_add = lambda items: None
365 # Widget
367 Gtk.widget_get_default_direction = Gtk.Widget.get_default_direction
368 orig_size_request = Gtk.Widget.size_request
370 def size_request(widget):
371 class SizeRequest(UserList):
372 def __init__(self, req):
373 self.height = req.height
374 self.width = req.width
375 UserList.__init__(self, [self.width, self.height])
376 return SizeRequest(orig_size_request(widget))
377 Gtk.Widget.size_request = size_request
378 Gtk.Widget.hide_all = Gtk.Widget.hide
380 def widget_set_flags(widget, flags):
381 assert flags == Gtk.CAN_DEFAULT, flags
382 widget.set_can_default(True)
384 Gtk.Widget.set_flags = widget_set_flags
386 class BaseGetter(object):
387 def __init__(self, context):
388 self.context = context
390 def __getitem__(self, state):
391 color = self.context.get_background_color(state)
392 return Gdk.Color(red=int(color.red * 65535),
393 green=int(color.green * 65535),
394 blue=int(color.blue * 65535))
396 class Styles(object):
397 def __init__(self, widget):
398 context = widget.get_style_context()
399 self.base = BaseGetter(context)
400 self.black = Gdk.Color(red=0, green=0, blue=0)
402 class StyleDescriptor(object):
403 def __get__(self, instance, class_):
404 return Styles(instance)
405 Gtk.Widget.style = StyleDescriptor()
407 # gtk.unixprint
409 class UnixPrint(object):
410 pass
411 unixprint = UnixPrint()
412 sys.modules['gtkunixprint'] = unixprint
414 # gtk.keysyms
416 class Keysyms(object):
417 pass
418 keysyms = Keysyms()
419 sys.modules['gtk.keysyms'] = keysyms
420 Gtk.keysyms = keysyms
421 for name in dir(Gdk):
422 if name.startswith('KEY_'):
423 target = name[4:]
424 if target[0] in '0123456789':
425 target = '_' + target
426 value = getattr(Gdk, name)
427 setattr(keysyms, target, value)
429 Gtk.TreePath.__len__ = lambda path: path.get_depth()
431 # TreeStore
433 Gtk.TreeStore.get_iter_root = Gtk.TreeStore.get_iter_first
435 def enable_vte():
436 gi.require_version('Vte', '0.0')
437 from gi.repository import Vte
438 sys.modules['vte'] = Vte
441 def enable_poppler():
442 gi.require_version('Poppler', '0.18')
443 from gi.repository import Poppler
444 sys.modules['poppler'] = Poppler
445 Poppler.pypoppler_version = (1, 0, 0)
448 def enable_webkit(version='1.0'):
449 gi.require_version('WebKit', version)
450 from gi.repository import WebKit
451 sys.modules['webkit'] = WebKit
452 WebKit.WebView.get_web_inspector = WebKit.WebView.get_inspector
455 def enable_gudev():
456 gi.require_version('GUdev', '1.0')
457 from gi.repository import GUdev
458 sys.modules['gudev'] = GUdev
461 def enable_gst():
462 gi.require_version('Gst', '0.10')
463 from gi.repository import Gst
464 sys.modules['gst'] = Gst
465 _install_enums(Gst)
466 Gst.registry_get_default = Gst.Registry.get_default
467 Gst.element_register = Gst.Element.register
468 Gst.element_factory_make = Gst.ElementFactory.make
469 Gst.caps_new_any = Gst.Caps.new_any
470 Gst.get_pygst_version = lambda: (0, 10, 19)
471 Gst.get_gst_version = lambda: (0, 10, 40)
473 from gi.repository import GstInterfaces
474 sys.modules['gst.interfaces'] = GstInterfaces
475 _install_enums(GstInterfaces)
477 from gi.repository import GstAudio
478 sys.modules['gst.audio'] = GstAudio
479 _install_enums(GstAudio)
481 from gi.repository import GstVideo
482 sys.modules['gst.video'] = GstVideo
483 _install_enums(GstVideo)
485 from gi.repository import GstBase
486 sys.modules['gst.base'] = GstBase
487 _install_enums(GstBase)
489 Gst.BaseTransform = GstBase.BaseTransform
490 Gst.BaseSink = GstBase.BaseSink
492 from gi.repository import GstController
493 sys.modules['gst.controller'] = GstController
494 _install_enums(GstController, dest=Gst)
496 from gi.repository import GstPbutils
497 sys.modules['gst.pbutils'] = GstPbutils
498 _install_enums(GstPbutils)
501 def enable_goocanvas():
502 gi.require_version('GooCanvas', '2.0')
503 from gi.repository import GooCanvas
504 sys.modules['goocanvas'] = GooCanvas
505 _install_enums(GooCanvas, strip='GOO_CANVAS_')
506 GooCanvas.ItemSimple = GooCanvas.CanvasItemSimple
507 GooCanvas.Item = GooCanvas.CanvasItem
508 GooCanvas.Image = GooCanvas.CanvasImage
509 GooCanvas.Group = GooCanvas.CanvasGroup
510 GooCanvas.Rect = GooCanvas.CanvasRect