pygtkcompat.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. # -*- Mode: Python; py-indent-offset: 4 -*-
  2. # vim: tabstop=4 shiftwidth=4 expandtab
  3. #
  4. # Copyright (C) 2011-2012 Johan Dahlin <johan@gnome.org>
  5. #
  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.
  10. #
  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.
  15. #
  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
  20. """
  21. PyGTK compatibility layer.
  22. This modules goes a little bit longer to maintain PyGTK compatibility than
  23. the normal overrides system.
  24. It is recommended to not depend on this layer, but only use it as an
  25. intermediate step when porting your application to PyGI.
  26. Compatibility might never be 100%, but the aim is to make it possible to run
  27. a well behaved PyGTK application mostly unmodified on top of PyGI.
  28. """
  29. import sys
  30. import warnings
  31. try:
  32. # Python 3
  33. from collections import UserList
  34. UserList # pyflakes
  35. with warnings.catch_warnings():
  36. warnings.simplefilter('ignore')
  37. from imp import reload
  38. except ImportError:
  39. # Python 2 ships that in a different module
  40. from UserList import UserList
  41. UserList # pyflakes
  42. import gi
  43. from gi.repository import GObject
  44. def _install_enums(module, dest=None, strip=''):
  45. if dest is None:
  46. dest = module
  47. modname = dest.__name__.rsplit('.', 1)[1].upper()
  48. for attr in dir(module):
  49. try:
  50. obj = getattr(module, attr, None)
  51. except:
  52. continue
  53. try:
  54. if issubclass(obj, GObject.GEnum):
  55. for value, enum in obj.__enum_values__.items():
  56. name = enum.value_name
  57. name = name.replace(modname + '_', '')
  58. if strip and name.startswith(strip):
  59. name = name[len(strip):]
  60. setattr(dest, name, enum)
  61. except TypeError:
  62. continue
  63. try:
  64. if issubclass(obj, GObject.GFlags):
  65. for value, flag in obj.__flags_values__.items():
  66. try:
  67. name = flag.value_names[-1].replace(modname + '_', '')
  68. except IndexError:
  69. # FIXME: this happens for some large flags which do not
  70. # fit into a long on 32 bit systems
  71. continue
  72. setattr(dest, name, flag)
  73. except TypeError:
  74. continue
  75. def enable():
  76. # gobject
  77. from gi.repository import GLib
  78. sys.modules['glib'] = GLib
  79. # gobject
  80. from gi.repository import GObject
  81. sys.modules['gobject'] = GObject
  82. from gi import _propertyhelper
  83. sys.modules['gobject.propertyhelper'] = _propertyhelper
  84. # gio
  85. from gi.repository import Gio
  86. sys.modules['gio'] = Gio
  87. _unset = object()
  88. def enable_gtk(version='3.0'):
  89. # set the default encoding like PyGTK
  90. reload(sys)
  91. if sys.version_info < (3, 0):
  92. sys.setdefaultencoding('utf-8')
  93. # atk
  94. gi.require_version('Atk', '1.0')
  95. from gi.repository import Atk
  96. sys.modules['atk'] = Atk
  97. _install_enums(Atk)
  98. # pango
  99. gi.require_version('Pango', '1.0')
  100. from gi.repository import Pango
  101. sys.modules['pango'] = Pango
  102. _install_enums(Pango)
  103. # pangocairo
  104. gi.require_version('PangoCairo', '1.0')
  105. from gi.repository import PangoCairo
  106. sys.modules['pangocairo'] = PangoCairo
  107. # gdk
  108. gi.require_version('Gdk', version)
  109. gi.require_version('GdkPixbuf', '2.0')
  110. from gi.repository import Gdk
  111. from gi.repository import GdkPixbuf
  112. sys.modules['gtk.gdk'] = Gdk
  113. _install_enums(Gdk)
  114. _install_enums(GdkPixbuf, dest=Gdk)
  115. Gdk._2BUTTON_PRESS = 5
  116. Gdk.BUTTON_PRESS = 4
  117. Gdk.screen_get_default = Gdk.Screen.get_default
  118. Gdk.Pixbuf = GdkPixbuf.Pixbuf
  119. Gdk.PixbufLoader = GdkPixbuf.PixbufLoader.new_with_type
  120. Gdk.pixbuf_new_from_data = GdkPixbuf.Pixbuf.new_from_data
  121. Gdk.pixbuf_new_from_file = GdkPixbuf.Pixbuf.new_from_file
  122. try:
  123. Gdk.pixbuf_new_from_file_at_scale = GdkPixbuf.Pixbuf.new_from_file_at_scale
  124. except AttributeError:
  125. pass
  126. Gdk.pixbuf_new_from_file_at_size = GdkPixbuf.Pixbuf.new_from_file_at_size
  127. Gdk.pixbuf_new_from_inline = GdkPixbuf.Pixbuf.new_from_inline
  128. Gdk.pixbuf_new_from_stream = GdkPixbuf.Pixbuf.new_from_stream
  129. Gdk.pixbuf_new_from_stream_at_scale = GdkPixbuf.Pixbuf.new_from_stream_at_scale
  130. Gdk.pixbuf_new_from_xpm_data = GdkPixbuf.Pixbuf.new_from_xpm_data
  131. Gdk.pixbuf_get_file_info = GdkPixbuf.Pixbuf.get_file_info
  132. orig_get_formats = GdkPixbuf.Pixbuf.get_formats
  133. def get_formats():
  134. formats = orig_get_formats()
  135. result = []
  136. def make_dict(format_):
  137. result = {}
  138. result['description'] = format_.get_description()
  139. result['name'] = format_.get_name()
  140. result['mime_types'] = format_.get_mime_types()
  141. result['extensions'] = format_.get_extensions()
  142. return result
  143. for format_ in formats:
  144. result.append(make_dict(format_))
  145. return result
  146. Gdk.pixbuf_get_formats = get_formats
  147. orig_get_frame_extents = Gdk.Window.get_frame_extents
  148. def get_frame_extents(window):
  149. try:
  150. try:
  151. rect = Gdk.Rectangle(0, 0, 0, 0)
  152. except TypeError:
  153. rect = Gdk.Rectangle()
  154. orig_get_frame_extents(window, rect)
  155. except TypeError:
  156. rect = orig_get_frame_extents(window)
  157. return rect
  158. Gdk.Window.get_frame_extents = get_frame_extents
  159. orig_get_origin = Gdk.Window.get_origin
  160. def get_origin(self):
  161. return orig_get_origin(self)[1:]
  162. Gdk.Window.get_origin = get_origin
  163. Gdk.screen_width = Gdk.Screen.width
  164. Gdk.screen_height = Gdk.Screen.height
  165. orig_gdk_window_get_geometry = Gdk.Window.get_geometry
  166. def gdk_window_get_geometry(window):
  167. return orig_gdk_window_get_geometry(window) + (window.get_visual().get_best_depth(),)
  168. Gdk.Window.get_geometry = gdk_window_get_geometry
  169. # gtk
  170. gi.require_version('Gtk', version)
  171. from gi.repository import Gtk
  172. sys.modules['gtk'] = Gtk
  173. Gtk.gdk = Gdk
  174. Gtk.pygtk_version = (2, 99, 0)
  175. Gtk.gtk_version = (Gtk.MAJOR_VERSION,
  176. Gtk.MINOR_VERSION,
  177. Gtk.MICRO_VERSION)
  178. _install_enums(Gtk)
  179. # Action
  180. def set_tool_item_type(menuaction, gtype):
  181. warnings.warn('set_tool_item_type() is not supported',
  182. gi.PyGIDeprecationWarning, stacklevel=2)
  183. Gtk.Action.set_tool_item_type = classmethod(set_tool_item_type)
  184. # Alignment
  185. orig_Alignment = Gtk.Alignment
  186. class Alignment(orig_Alignment):
  187. def __init__(self, xalign=0.0, yalign=0.0, xscale=0.0, yscale=0.0):
  188. orig_Alignment.__init__(self)
  189. self.props.xalign = xalign
  190. self.props.yalign = yalign
  191. self.props.xscale = xscale
  192. self.props.yscale = yscale
  193. Gtk.Alignment = Alignment
  194. # Box
  195. orig_pack_end = Gtk.Box.pack_end
  196. def pack_end(self, child, expand=True, fill=True, padding=0):
  197. orig_pack_end(self, child, expand, fill, padding)
  198. Gtk.Box.pack_end = pack_end
  199. orig_pack_start = Gtk.Box.pack_start
  200. def pack_start(self, child, expand=True, fill=True, padding=0):
  201. orig_pack_start(self, child, expand, fill, padding)
  202. Gtk.Box.pack_start = pack_start
  203. # TreeViewColumn
  204. orig_tree_view_column_pack_end = Gtk.TreeViewColumn.pack_end
  205. def tree_view_column_pack_end(self, cell, expand=True):
  206. orig_tree_view_column_pack_end(self, cell, expand)
  207. Gtk.TreeViewColumn.pack_end = tree_view_column_pack_end
  208. orig_tree_view_column_pack_start = Gtk.TreeViewColumn.pack_start
  209. def tree_view_column_pack_start(self, cell, expand=True):
  210. orig_tree_view_column_pack_start(self, cell, expand)
  211. Gtk.TreeViewColumn.pack_start = tree_view_column_pack_start
  212. # CellLayout
  213. orig_cell_pack_end = Gtk.CellLayout.pack_end
  214. def cell_pack_end(self, cell, expand=True):
  215. orig_cell_pack_end(self, cell, expand)
  216. Gtk.CellLayout.pack_end = cell_pack_end
  217. orig_cell_pack_start = Gtk.CellLayout.pack_start
  218. def cell_pack_start(self, cell, expand=True):
  219. orig_cell_pack_start(self, cell, expand)
  220. Gtk.CellLayout.pack_start = cell_pack_start
  221. orig_set_cell_data_func = Gtk.CellLayout.set_cell_data_func
  222. def set_cell_data_func(self, cell, func, user_data=_unset):
  223. def callback(*args):
  224. if args[-1] == _unset:
  225. args = args[:-1]
  226. return func(*args)
  227. orig_set_cell_data_func(self, cell, callback, user_data)
  228. Gtk.CellLayout.set_cell_data_func = set_cell_data_func
  229. # CellRenderer
  230. class GenericCellRenderer(Gtk.CellRenderer):
  231. pass
  232. Gtk.GenericCellRenderer = GenericCellRenderer
  233. # ComboBox
  234. orig_combo_row_separator_func = Gtk.ComboBox.set_row_separator_func
  235. def combo_row_separator_func(self, func, user_data=_unset):
  236. def callback(*args):
  237. if args[-1] == _unset:
  238. args = args[:-1]
  239. return func(*args)
  240. orig_combo_row_separator_func(self, callback, user_data)
  241. Gtk.ComboBox.set_row_separator_func = combo_row_separator_func
  242. # ComboBoxEntry
  243. class ComboBoxEntry(Gtk.ComboBox):
  244. def __init__(self, **kwds):
  245. Gtk.ComboBox.__init__(self, has_entry=True, **kwds)
  246. def set_text_column(self, text_column):
  247. self.set_entry_text_column(text_column)
  248. def get_text_column(self):
  249. return self.get_entry_text_column()
  250. Gtk.ComboBoxEntry = ComboBoxEntry
  251. def combo_box_entry_new():
  252. return Gtk.ComboBoxEntry()
  253. Gtk.combo_box_entry_new = combo_box_entry_new
  254. def combo_box_entry_new_with_model(model):
  255. return Gtk.ComboBoxEntry(model=model)
  256. Gtk.combo_box_entry_new_with_model = combo_box_entry_new_with_model
  257. # Container
  258. def install_child_property(container, flag, pspec):
  259. warnings.warn('install_child_property() is not supported',
  260. gi.PyGIDeprecationWarning, stacklevel=2)
  261. Gtk.Container.install_child_property = classmethod(install_child_property)
  262. def new_text():
  263. combo = Gtk.ComboBox()
  264. model = Gtk.ListStore(str)
  265. combo.set_model(model)
  266. combo.set_entry_text_column(0)
  267. return combo
  268. Gtk.combo_box_new_text = new_text
  269. def append_text(self, text):
  270. model = self.get_model()
  271. model.append([text])
  272. Gtk.ComboBox.append_text = append_text
  273. Gtk.expander_new_with_mnemonic = Gtk.Expander.new_with_mnemonic
  274. Gtk.icon_theme_get_default = Gtk.IconTheme.get_default
  275. Gtk.image_new_from_pixbuf = Gtk.Image.new_from_pixbuf
  276. Gtk.image_new_from_stock = Gtk.Image.new_from_stock
  277. Gtk.image_new_from_animation = Gtk.Image.new_from_animation
  278. Gtk.image_new_from_icon_set = Gtk.Image.new_from_icon_set
  279. Gtk.image_new_from_file = Gtk.Image.new_from_file
  280. Gtk.settings_get_default = Gtk.Settings.get_default
  281. Gtk.window_set_default_icon = Gtk.Window.set_default_icon
  282. try:
  283. Gtk.clipboard_get = Gtk.Clipboard.get
  284. except AttributeError:
  285. pass
  286. # AccelGroup
  287. Gtk.AccelGroup.connect_group = Gtk.AccelGroup.connect
  288. # StatusIcon
  289. Gtk.status_icon_position_menu = Gtk.StatusIcon.position_menu
  290. Gtk.StatusIcon.set_tooltip = Gtk.StatusIcon.set_tooltip_text
  291. # Scale
  292. orig_HScale = Gtk.HScale
  293. orig_VScale = Gtk.VScale
  294. class HScale(orig_HScale):
  295. def __init__(self, adjustment=None):
  296. orig_HScale.__init__(self, adjustment=adjustment)
  297. Gtk.HScale = HScale
  298. class VScale(orig_VScale):
  299. def __init__(self, adjustment=None):
  300. orig_VScale.__init__(self, adjustment=adjustment)
  301. Gtk.VScale = VScale
  302. Gtk.stock_add = lambda items: None
  303. # Widget
  304. Gtk.Widget.window = property(fget=Gtk.Widget.get_window)
  305. Gtk.widget_get_default_direction = Gtk.Widget.get_default_direction
  306. orig_size_request = Gtk.Widget.size_request
  307. def size_request(widget):
  308. class SizeRequest(UserList):
  309. def __init__(self, req):
  310. self.height = req.height
  311. self.width = req.width
  312. UserList.__init__(self, [self.width, self.height])
  313. return SizeRequest(orig_size_request(widget))
  314. Gtk.Widget.size_request = size_request
  315. Gtk.Widget.hide_all = Gtk.Widget.hide
  316. class BaseGetter(object):
  317. def __init__(self, context):
  318. self.context = context
  319. def __getitem__(self, state):
  320. color = self.context.get_background_color(state)
  321. return Gdk.Color(red=int(color.red * 65535),
  322. green=int(color.green * 65535),
  323. blue=int(color.blue * 65535))
  324. class Styles(object):
  325. def __init__(self, widget):
  326. context = widget.get_style_context()
  327. self.base = BaseGetter(context)
  328. self.black = Gdk.Color(red=0, green=0, blue=0)
  329. class StyleDescriptor(object):
  330. def __get__(self, instance, class_):
  331. return Styles(instance)
  332. Gtk.Widget.style = StyleDescriptor()
  333. # TextView
  334. orig_text_view_scroll_to_mark = Gtk.TextView.scroll_to_mark
  335. def text_view_scroll_to_mark(self, mark, within_margin,
  336. use_align=False, xalign=0.5, yalign=0.5):
  337. return orig_text_view_scroll_to_mark(self, mark, within_margin,
  338. use_align, xalign, yalign)
  339. Gtk.TextView.scroll_to_mark = text_view_scroll_to_mark
  340. # Window
  341. orig_set_geometry_hints = Gtk.Window.set_geometry_hints
  342. def set_geometry_hints(self, geometry_widget=None,
  343. min_width=-1, min_height=-1, max_width=-1, max_height=-1,
  344. base_width=-1, base_height=-1, width_inc=-1, height_inc=-1,
  345. min_aspect=-1.0, max_aspect=-1.0):
  346. geometry = Gdk.Geometry()
  347. geom_mask = Gdk.WindowHints(0)
  348. if min_width >= 0 or min_height >= 0:
  349. geometry.min_width = max(min_width, 0)
  350. geometry.min_height = max(min_height, 0)
  351. geom_mask |= Gdk.WindowHints.MIN_SIZE
  352. if max_width >= 0 or max_height >= 0:
  353. geometry.max_width = max(max_width, 0)
  354. geometry.max_height = max(max_height, 0)
  355. geom_mask |= Gdk.WindowHints.MAX_SIZE
  356. if base_width >= 0 or base_height >= 0:
  357. geometry.base_width = max(base_width, 0)
  358. geometry.base_height = max(base_height, 0)
  359. geom_mask |= Gdk.WindowHints.BASE_SIZE
  360. if width_inc >= 0 or height_inc >= 0:
  361. geometry.width_inc = max(width_inc, 0)
  362. geometry.height_inc = max(height_inc, 0)
  363. geom_mask |= Gdk.WindowHints.RESIZE_INC
  364. if min_aspect >= 0.0 or max_aspect >= 0.0:
  365. if min_aspect <= 0.0 or max_aspect <= 0.0:
  366. raise TypeError("aspect ratios must be positive")
  367. geometry.min_aspect = min_aspect
  368. geometry.max_aspect = max_aspect
  369. geom_mask |= Gdk.WindowHints.ASPECT
  370. return orig_set_geometry_hints(self, geometry_widget, geometry, geom_mask)
  371. Gtk.Window.set_geometry_hints = set_geometry_hints
  372. Gtk.window_list_toplevels = Gtk.Window.list_toplevels
  373. Gtk.window_set_default_icon_name = Gtk.Window.set_default_icon_name
  374. # gtk.unixprint
  375. class UnixPrint(object):
  376. pass
  377. unixprint = UnixPrint()
  378. sys.modules['gtkunixprint'] = unixprint
  379. # gtk.keysyms
  380. with warnings.catch_warnings():
  381. warnings.simplefilter('ignore', category=RuntimeWarning)
  382. from gi.overrides import keysyms
  383. sys.modules['gtk.keysyms'] = keysyms
  384. Gtk.keysyms = keysyms
  385. from . import generictreemodel
  386. Gtk.GenericTreeModel = generictreemodel.GenericTreeModel
  387. def enable_vte():
  388. gi.require_version('Vte', '0.0')
  389. from gi.repository import Vte
  390. sys.modules['vte'] = Vte
  391. def enable_poppler():
  392. gi.require_version('Poppler', '0.18')
  393. from gi.repository import Poppler
  394. sys.modules['poppler'] = Poppler
  395. Poppler.pypoppler_version = (1, 0, 0)
  396. def enable_webkit(version='1.0'):
  397. gi.require_version('WebKit', version)
  398. from gi.repository import WebKit
  399. sys.modules['webkit'] = WebKit
  400. WebKit.WebView.get_web_inspector = WebKit.WebView.get_inspector
  401. def enable_gudev():
  402. gi.require_version('GUdev', '1.0')
  403. from gi.repository import GUdev
  404. sys.modules['gudev'] = GUdev
  405. def enable_gst():
  406. gi.require_version('Gst', '0.10')
  407. from gi.repository import Gst
  408. sys.modules['gst'] = Gst
  409. _install_enums(Gst)
  410. Gst.registry_get_default = Gst.Registry.get_default
  411. Gst.element_register = Gst.Element.register
  412. Gst.element_factory_make = Gst.ElementFactory.make
  413. Gst.caps_new_any = Gst.Caps.new_any
  414. Gst.get_pygst_version = lambda: (0, 10, 19)
  415. Gst.get_gst_version = lambda: (0, 10, 40)
  416. from gi.repository import GstInterfaces
  417. sys.modules['gst.interfaces'] = GstInterfaces
  418. _install_enums(GstInterfaces)
  419. from gi.repository import GstAudio
  420. sys.modules['gst.audio'] = GstAudio
  421. _install_enums(GstAudio)
  422. from gi.repository import GstVideo
  423. sys.modules['gst.video'] = GstVideo
  424. _install_enums(GstVideo)
  425. from gi.repository import GstBase
  426. sys.modules['gst.base'] = GstBase
  427. _install_enums(GstBase)
  428. Gst.BaseTransform = GstBase.BaseTransform
  429. Gst.BaseSink = GstBase.BaseSink
  430. from gi.repository import GstController
  431. sys.modules['gst.controller'] = GstController
  432. _install_enums(GstController, dest=Gst)
  433. from gi.repository import GstPbutils
  434. sys.modules['gst.pbutils'] = GstPbutils
  435. _install_enums(GstPbutils)
  436. def enable_goocanvas():
  437. gi.require_version('GooCanvas', '2.0')
  438. from gi.repository import GooCanvas
  439. sys.modules['goocanvas'] = GooCanvas
  440. _install_enums(GooCanvas, strip='GOO_CANVAS_')
  441. GooCanvas.ItemSimple = GooCanvas.CanvasItemSimple
  442. GooCanvas.Item = GooCanvas.CanvasItem
  443. GooCanvas.Image = GooCanvas.CanvasImage
  444. GooCanvas.Group = GooCanvas.CanvasGroup
  445. GooCanvas.Rect = GooCanvas.CanvasRect