binding_helper.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 # Copyright (c) 2011, Dirk Thomas, Dorian Scholz, TU Darmstadt
00004 # All rights reserved.
00005 #
00006 # Redistribution and use in source and binary forms, with or without
00007 # modification, are permitted provided that the following conditions
00008 # are met:
00009 #
00010 #   * Redistributions of source code must retain the above copyright
00011 #     notice, this list of conditions and the following disclaimer.
00012 #   * Redistributions in binary form must reproduce the above
00013 #     copyright notice, this list of conditions and the following
00014 #     disclaimer in the documentation and/or other materials provided
00015 #     with the distribution.
00016 #   * Neither the name of the TU Darmstadt nor the names of its
00017 #     contributors may be used to endorse or promote products derived
00018 #     from this software without specific prior written permission.
00019 #
00020 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024 # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 # POSSIBILITY OF SUCH DAMAGE.
00032 
00033 import os
00034 import sys
00035 import __builtin__
00036 
00037 
00038 def _select_qt_binding(binding_name=None):
00039     global QT_BINDING, QT_BINDING_VERSION
00040 
00041     # order of default bindings can be changed here
00042     DEFAULT_BINDING_ORDER = ['pyqt', 'pyside']
00043 
00044     # determine binding preference
00045     if binding_name is not None:
00046         if binding_name not in DEFAULT_BINDING_ORDER:
00047             raise ImportError('Qt binding "%s" is unknown' % binding_name)
00048         DEFAULT_BINDING_ORDER = [binding_name]
00049 
00050     required_modules = [
00051         'QtCore',
00052         'QtGui'
00053     ]
00054     optional_modules = [
00055         'QtDeclarative',
00056         'QtMultimedia',
00057         'QtNetwork',
00058         'QtOpenGL',
00059         'QtOpenVG',
00060         'QtScript',
00061         'QtScriptTools'
00062         'QtSql',
00063         'QtSvg',
00064         'QtWebKit',
00065         'QtXml',
00066         'QtXmlPatterns',
00067     ]
00068 
00069     # try to load preferred bindings
00070     error_msgs = []
00071     for binding_name in DEFAULT_BINDING_ORDER:
00072         try:
00073             binding_loader = getattr(sys.modules[__name__], '_load_%s' % binding_name, None)
00074             if binding_loader is not None:
00075                 QT_BINDING_VERSION = binding_loader(required_modules, optional_modules)
00076                 QT_BINDING = binding_name
00077                 break
00078             else:
00079                 error_msgs.append('  Binding loader "_load_%s" not found.' % binding_name)
00080         except ImportError, e:
00081             error_msgs.append('  ImportError for "%s": %s' % (binding_name, e))
00082 
00083     if QT_BINDING is None:
00084         raise ImportError('Could not find Qt binding (looked for "%s"):\n%s' % (DEFAULT_BINDING_ORDER, '\n'.join(error_msgs)))
00085 
00086 
00087 def _register_binding_module(module_name, module):
00088     # register module using only its own name (TODO: legacy compatibility, remove when possible)
00089     sys.modules[module_name] = module
00090     # add module to the binding modules
00091     QT_BINDING_MODULES[module_name] = module
00092 
00093 
00094 def _named_import(name):
00095     parts = name.split('.')
00096     assert(len(parts) >= 2)
00097     module = __builtin__.__import__(name)
00098     for m in parts[1:]:
00099         module = module.__dict__[m]
00100     module_name = parts[-1]
00101     _register_binding_module(module_name, module)
00102 
00103 
00104 def _named_optional_import(name):
00105     try:
00106         _named_import(name)
00107     except ImportError:
00108         pass
00109 
00110 
00111 def _load_pyqt(required_modules, optional_modules):
00112     # set environment variable QT_API for matplotlib
00113     os.environ['QT_API'] = 'pyqt'
00114 
00115     # select PyQt4 API, see http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/incompatible_apis.html
00116     import sip
00117     try:
00118         sip.setapi('QDate', 2)
00119         sip.setapi('QDateTime', 2)
00120         sip.setapi('QString', 2)
00121         sip.setapi('QTextStream', 2)
00122         sip.setapi('QTime', 2)
00123         sip.setapi('QUrl', 2)
00124         sip.setapi('QVariant', 2)
00125     except ValueError, e:
00126         raise RuntimeError('Could not set API version (%s): did you import PyQt4 directly?' % e)
00127 
00128     # register required and optional PyQt4 modules
00129     for module_name in required_modules:
00130         _named_import('PyQt4.%s' % module_name)
00131     for module_name in optional_modules:
00132         _named_optional_import('PyQt4.%s' % module_name)
00133 
00134     # set some names for compatibility with PySide
00135     sys.modules['QtCore'].Signal = sys.modules['QtCore'].pyqtSignal
00136     sys.modules['QtCore'].Slot = sys.modules['QtCore'].pyqtSlot
00137     sys.modules['QtCore'].Property = sys.modules['QtCore'].pyqtProperty
00138 
00139     # try to register PyQt4.Qwt5 module
00140     try:
00141         import PyQt4.Qwt5
00142         _register_binding_module('Qwt', PyQt4.Qwt5)
00143     except ImportError:
00144         pass
00145 
00146     global loadUi
00147 
00148     def loadUi(uifile, baseinstance=None, custom_widgets=None):
00149         from PyQt4 import uic
00150         return uic.loadUi(uifile, baseinstance=baseinstance)
00151 
00152     # override specific function to improve compatibility between different bindings
00153     from QtGui import QFileDialog
00154     QFileDialog.getOpenFileName = QFileDialog.getOpenFileNameAndFilter
00155     QFileDialog.getSaveFileName = QFileDialog.getSaveFileNameAndFilter
00156 
00157     import PyQt4.QtCore
00158     return PyQt4.QtCore.PYQT_VERSION_STR
00159 
00160 
00161 def _load_pyside(required_modules, optional_modules):
00162     # set environment variable QT_API for matplotlib
00163     os.environ['QT_API'] = 'pyside'
00164 
00165     # register required and optional PySide modules
00166     for module_name in required_modules:
00167         _named_import('PySide.%s' % module_name)
00168     for module_name in optional_modules:
00169         _named_optional_import('PySide.%s' % module_name)
00170 
00171     # set some names for compatibility with PyQt4
00172     sys.modules['QtCore'].pyqtSignal = sys.modules['QtCore'].Signal
00173     sys.modules['QtCore'].pyqtSlot = sys.modules['QtCore'].Slot
00174     sys.modules['QtCore'].pyqtProperty = sys.modules['QtCore'].Property
00175 
00176     # try to register PySideQwt module
00177     try:
00178         import PySideQwt
00179         _register_binding_module('Qwt', PySideQwt)
00180     except ImportError:
00181         pass
00182 
00183     global loadUi
00184 
00185     def loadUi(uifile, baseinstance=None, custom_widgets=None):
00186         from PySide.QtUiTools import QUiLoader
00187         from PySide.QtCore import QMetaObject
00188 
00189         class CustomUiLoader(QUiLoader):
00190             class_aliases = {
00191                 'Line': 'QFrame',
00192             }
00193 
00194             def __init__(self, baseinstance=None, custom_widgets=None):
00195                 super(CustomUiLoader, self).__init__(baseinstance)
00196                 self._base_instance = baseinstance
00197                 self._custom_widgets = custom_widgets or {}
00198 
00199             def createWidget(self, class_name, parent=None, name=''):
00200                 # don't create the top-level widget, if a base instance is set
00201                 if self._base_instance is not None and parent is None:
00202                     return self._base_instance
00203 
00204                 if class_name in self._custom_widgets:
00205                     widget = self._custom_widgets[class_name](parent)
00206                 else:
00207                     widget = QUiLoader.createWidget(self, class_name, parent, name)
00208 
00209                 if str(type(widget)).find(self.class_aliases.get(class_name, class_name)) < 0:
00210                     sys.modules['QtCore'].qDebug(str('PySide.loadUi(): could not find widget class "%s", defaulting to "%s"' % (class_name, type(widget))))
00211 
00212                 if self._base_instance is not None:
00213                     setattr(self._base_instance, name, widget)
00214 
00215                 return widget
00216 
00217         loader = CustomUiLoader(baseinstance, custom_widgets)
00218 
00219         # instead of passing the custom widgets, they should be registered using QUiLoader.registerCustomWidget(),
00220         # but this does not work in PySide 1.0.6: it simply segfaults...
00221         #loader = CustomUiLoader(baseinstance)
00222         #custom_widgets = custom_widgets or {}
00223         #for custom_widget in custom_widgets.values():
00224         #    loader.registerCustomWidget(custom_widget)
00225 
00226         ui = loader.load(uifile)
00227         QMetaObject.connectSlotsByName(ui)
00228         return ui
00229 
00230     import PySide
00231     return PySide.__version__
00232 
00233 
00234 QT_BINDING = None
00235 QT_BINDING_MODULES = {}
00236 QT_BINDING_VERSION = None
00237 
00238 _select_qt_binding(getattr(sys, 'SELECT_QT_BINDING', None))


python_qt_binding
Author(s): Dave Hershberger, Dirk Thomas
autogenerated on Fri Jan 3 2014 11:44:20