Canonical Voices

Posts tagged with 'pyside'

mandel

The following bug I have been faced with has made me loose more time that I would have expected and therefore I think is a good idea to describe it so that the rest of the internet can take advantage of my wasted time and also to keep a record of my stupidity.

After building the .exe file of the ubuntu-sso port to windows I was getting the following error at runtime:

Cannot mix incompatible Qt library (version 0x40701) with this library (version 0x40702)

Usually this means that you have two different version of Qt installed are you are mixing the libraries (.dll in this case because I was dealing with Windows). My initial reaction was to look at my Qt setup in the machine and compared the version installed in the system and that used by PyQt. Let me tell you that is a waste of time. The real reason behind this runtime error was the fact that I was using the qtreactor and I had PyQt and PySide installed in my system.

When not freezing the application, the fact that you have both packages installed is not a problem what so ever, but with py2exe it is. Py2exe bundles all the dependencies you app has and due to the fact hat qtreactor does the following:

try:
    from PyQt4.QtCore import QSocketNotifier, QObject, SIGNAL, QTimer, QCoreApplication
    from PyQt4.QtCore import QEventLoop
except ImportError:
    from PySide.QtCore import QSocketNotifier, QObject, SIGNAL, QTimer, QCoreApplication
    from PySide.QtCore import QEventLoop

both, PySide and PyQt were included in the frozen app. The problem arises due to this fact. When py2exe adds both libs, it copies the Qt dlls you depend on, and if PySide and PYQt depend on different versions (which is what was happening in my system) you might run into the issue of getting dlls from different versions because py2exe will override the already copied dlls without telling you.

In summary if you get the above runtime error, take a look to see if PySide and PyQt have ben included in your frozen app and if they depend in different versions of Qt.

Read more
mandel

In some cases you might find yourself in the situation of wanting to use gettext in a PyQt project in which you have .ui files generated using QtDesigner.

For those kind of situations is a good idea to extend the uic compiler form PyQt. he following example shows how to do so in a distutils command.

class QtBuild(build_extra.build_extra):
    """Build PyQt (.ui) files and resources."""
 
    description = "build PyQt GUIs (.ui)."
 
    def compile_ui(self, ui_file, py_file=None):
        """Compile the .ui files to python modules."""
        # Search for pyuic4 in python bin dir, then in the $Path.
        if py_file is None:
            # go from the ui_file in the data folder to the
            # python file in the qt moodule
            py_file = os.path.split(ui_file)[1]
            py_file = os.path.splitext(py_file)[0] + '_ui.py'
            py_file = os.path.join('package', 'qt', py_file)
        # we indeed want to catch Exception, is ugle but w need it
        # pylint: disable=W0703
        try:
            # import the uic compiler from pyqt and generate the 
            # .py files something similar could be done with pyside
            # but that is left as an exercise for the reader.
            from PyQt4 import uic
            fp = open(py_file, 'w')
            uic.compileUi(ui_file, fp)
            fp.close()
            log.info('Compiled %s into %s', ui_file, py_file)
        except Exception, e:
            self.warn('Unable to compile user interface %s: %s',
                           py_file, e)
            if not os.path.exists(py_file) or\
                                            not file(py_file).read():
                raise SystemExit(1)
            return
        # pylint: enable=W0703
 
    def run(self):
        """Execute the command."""
        self._wrapuic()
        basepath = os.path.join('data',  'qt')
        for dirpath, _, filenames in os.walk(basepath):
            for filename in filenames:
                if filename.endswith('.ui'):
                    self.compile_ui(os.path.join(dirpath, filename))
 
    # pylint: disable=E1002
    _wrappeduic = False
    @classmethod
    def _wrapuic(cls):
        """Wrap uic to use gettext's _() in place of tr()"""
        if cls._wrappeduic:
            return
 
        from PyQt4.uic.Compiler import compiler, qtproxies, indenter
 
        # pylint: disable=C0103
        class _UICompiler(compiler.UICompiler):
            """Speciallized compiler for qt .ui files."""
            def createToplevelWidget(self, classname, widgetname):
                o = indenter.getIndenter()
                o.level = 0
                o.write('from module.with.gettext.setup import _')
                return super(_UICompiler, self).createToplevelWidget(
                                   classname, widgetname)
        compiler.UICompiler = _UICompiler
 
        class _i18n_string(qtproxies.i18n_string):
            """Provide a translated text."""
 
            def __str__(self):
                return "_('%s')" % self.string.encode(
                                                'string-escape')
 
        qtproxies.i18n_string = _i18n_string
 
        cls._wrappeduic = True
        # pylint: enable=C0103
    # pylint: enable=E1002

The above should be doable with PySide, but that is left as an exercise for the reader.

Read more