binding_helper.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 # Copyright (c) 2011, Dirk Thomas, Dorian Scholz, TU Darmstadt
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 #
10 # * Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # * Redistributions in binary form must reproduce the above
13 # copyright notice, this list of conditions and the following
14 # disclaimer in the documentation and/or other materials provided
15 # with the distribution.
16 # * Neither the name of the TU Darmstadt nor the names of its
17 # contributors may be used to endorse or promote products derived
18 # from this software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 # POSSIBILITY OF SUCH DAMAGE.
32 
33 try:
34  import __builtin__ as builtins
35 except ImportError:
36  # since the 'future' package provides a 'builtins' module in Python 2
37  # this must not be checked second
38  import builtins
39 import os
40 import sys
41 import traceback
42 
43 
44 QT_BINDING = None
45 QT_BINDING_MODULES = {}
46 QT_BINDING_VERSION = None
47 
48 
49 def _select_qt_binding(binding_name=None, binding_order=None):
50  global QT_BINDING, QT_BINDING_VERSION
51 
52  # order of default bindings can be changed here
53  DEFAULT_BINDING_ORDER = ['pyqt', 'pyside']
54  binding_order = binding_order or DEFAULT_BINDING_ORDER
55 
56  # determine binding preference
57  if binding_name:
58  if binding_name not in binding_order:
59  raise ImportError("Qt binding '%s' is unknown" % binding_name)
60  binding_order = [binding_name]
61 
62  required_modules = [
63  'QtCore',
64  'QtGui',
65  'QtWidgets',
66  ]
67  optional_modules = [
68  'QtBluetooth',
69  'QtDBus',
70  'QtDesigner',
71  'QtHelp',
72  'QtLocation',
73  'QtMultimedia',
74  'QtMultimediaWidgets',
75  'QtNetwork',
76  'QNetworkAuth',
77  'QtNfc',
78  'QtOpenGL',
79  'QtPositioning',
80  'QtPrintSupport',
81  'QtQml',
82  'QtQuick',
83  'QtQuickWidgets',
84  'QtScript',
85  'QtScriptTools',
86  'QtSensors',
87  'QtSerialPort',
88  'QtSql',
89  'QtSvg',
90  'QtTest',
91  'QtWebChannel',
92  'QtWebEngine', # Qt 5.6 and higher
93  'QtWebEngineCore',
94  'QtWebEngineWidgets',
95  'QtWebKitWidgets', # Qt 5.0 - 5.5
96  'QtWebSockets',
97  'QtX11Extras',
98  'QtXml',
99  'QtXmlPatterns',
100  ]
101 
102  # try to load preferred bindings
103  error_msgs = []
104  for binding_name in binding_order:
105  try:
106  binding_loader = getattr(sys.modules[__name__], '_load_%s' % binding_name, None)
107  if binding_loader:
108  QT_BINDING_VERSION = binding_loader(required_modules, optional_modules)
109  QT_BINDING = binding_name
110  break
111  else:
112  error_msgs.append(" Binding loader '_load_%s' not found." % binding_name)
113  except ImportError as e:
114  error_msgs.append(" ImportError for '%s': %s\n%s" %
115  (binding_name, e, traceback.format_exc()))
116 
117  if not QT_BINDING:
118  raise ImportError(
119  "Could not find Qt binding (looked for: %s):\n%s" %
120  (', '.join(["'%s'" % b for b in binding_order]), '\n'.join(error_msgs)))
121 
122 
123 def _register_binding_module(module_name, module):
124  # register module using only its own name (TODO: legacy compatibility, remove when possible)
125  sys.modules[module_name] = module
126  # add module to the binding modules
127  QT_BINDING_MODULES[module_name] = module
128 
129 
130 def _named_import(name):
131  parts = name.split('.')
132  assert(len(parts) >= 2)
133  module = builtins.__import__(name)
134  for m in parts[1:]:
135  module = module.__dict__[m]
136  module_name = parts[-1]
137  _register_binding_module(module_name, module)
138 
139 
141  try:
142  _named_import(name)
143  except ImportError:
144  pass
145 
146 
147 def _load_pyqt(required_modules, optional_modules):
148  # set environment variable QT_API for matplotlib
149  os.environ['QT_API'] = 'pyqt'
150 
151  # register required and optional PyQt modules
152  for module_name in required_modules:
153  _named_import('PyQt5.%s' % module_name)
154  for module_name in optional_modules:
155  _named_optional_import('PyQt5.%s' % module_name)
156 
157  # set some names for compatibility with PySide
158  sys.modules['QtCore'].Signal = sys.modules['QtCore'].pyqtSignal
159  sys.modules['QtCore'].Slot = sys.modules['QtCore'].pyqtSlot
160  sys.modules['QtCore'].Property = sys.modules['QtCore'].pyqtProperty
161 
162  # try to register Qwt module
163  try:
164  import PyQt5.Qwt5
165  _register_binding_module('Qwt', PyQt5.Qwt5)
166  except ImportError:
167  pass
168 
169  global _loadUi
170 
171  def _loadUi(uifile, baseinstance=None, custom_widgets_=None):
172  from PyQt5 import uic
173  return uic.loadUi(uifile, baseinstance=baseinstance)
174 
175  import PyQt5.QtCore
176  return PyQt5.QtCore.PYQT_VERSION_STR
177 
178 
179 def _load_pyside(required_modules, optional_modules):
180  # set environment variable QT_API for matplotlib
181  os.environ['QT_API'] = 'pyside'
182 
183  # register required and optional PySide modules
184  for module_name in required_modules:
185  _named_import('PySide2.%s' % module_name)
186  for module_name in optional_modules:
187  _named_optional_import('PySide2.%s' % module_name)
188 
189  # set some names for compatibility with PyQt
190  sys.modules['QtCore'].pyqtSignal = sys.modules['QtCore'].Signal
191  sys.modules['QtCore'].pyqtSlot = sys.modules['QtCore'].Slot
192  sys.modules['QtCore'].pyqtProperty = sys.modules['QtCore'].Property
193 
194  # try to register PySideQwt module
195  try:
196  import PySideQwt
197  _register_binding_module('Qwt', PySideQwt)
198  except ImportError:
199  pass
200 
201  global _loadUi
202 
203  def _loadUi(uifile, baseinstance=None, custom_widgets=None):
204  from PySide2.QtUiTools import QUiLoader
205  from PySide2.QtCore import QMetaObject
206 
207  class CustomUiLoader(QUiLoader):
208  class_aliases = {
209  'Line': 'QFrame',
210  }
211 
212  def __init__(self, baseinstance=None, custom_widgets=None):
213  super(CustomUiLoader, self).__init__(baseinstance)
214  self._base_instance = baseinstance
215  self._custom_widgets = custom_widgets or {}
216 
217  def createWidget(self, class_name, parent=None, name=''):
218  # don't create the top-level widget, if a base instance is set
219  if self._base_instance and not parent:
220  return self._base_instance
221 
222  if class_name in self._custom_widgets:
223  widget = self._custom_widgets[class_name](parent)
224  else:
225  widget = QUiLoader.createWidget(self, class_name, parent, name)
226 
227  if str(type(widget)).find(self.class_aliases.get(class_name, class_name)) < 0:
228  sys.modules['QtCore'].qDebug(
229  'PySide.loadUi(): could not find widget class "%s", defaulting to "%s"' %
230  (class_name, type(widget)))
231 
232  if self._base_instance:
233  setattr(self._base_instance, name, widget)
234 
235  return widget
236 
237  loader = CustomUiLoader(baseinstance, custom_widgets)
238 
239  # instead of passing the custom widgets, they should be registered using QUiLoader.registerCustomWidget(),
240  # but this does not work in PySide 1.0.6: it simply segfaults...
241  # loader = CustomUiLoader(baseinstance)
242  # custom_widgets = custom_widgets or {}
243  # for custom_widget in custom_widgets.values():
244  # loader.registerCustomWidget(custom_widget)
245 
246  ui = loader.load(uifile)
247  QMetaObject.connectSlotsByName(ui)
248  return ui
249 
250  import PySide2
251  return PySide2.__version__
252 
253 
254 def loadUi(uifile, baseinstance=None, custom_widgets=None):
255  """
256  @type uifile: str
257  @param uifile: Absolute path of .ui file
258  @type baseinstance: QWidget
259  @param baseinstance: the optional instance of the Qt base class.
260  If specified then the user interface is created in
261  it. Otherwise a new instance of the base class is
262  automatically created.
263  @type custom_widgets: dict of {str:QWidget}
264  @param custom_widgets: Class name and type of the custom classes used
265  in uifile if any. This can be None if no custom
266  class is in use. (Note: this is only necessary
267  for PySide, see
268  http://answers.ros.org/question/56382/what-does-python_qt_bindingloaduis-3rd-arg-do-in-pyqt-binding/
269  for more information)
270  """
271  return _loadUi(uifile, baseinstance, custom_widgets)
272 
273 
275  getattr(sys, 'SELECT_QT_BINDING', None),
276  getattr(sys, 'SELECT_QT_BINDING_ORDER', None),
277 )
def _select_qt_binding(binding_name=None, binding_order=None)
def _register_binding_module(module_name, module)
def loadUi(uifile, baseinstance=None, custom_widgets=None)
def _load_pyside(required_modules, optional_modules)
def _load_pyqt(required_modules, optional_modules)


python_qt_binding
Author(s): Dave Hershberger, Dorian Scholz, Dirk Thomas
autogenerated on Tue Apr 13 2021 02:23:57