Source code for ClearMap.gui.pyuic_utils

# -*- coding: utf-8 -*-
"""
pyuic_utils
===========

Essentially a reimplementation of loadUiType from PyQt5 to allow monkey patching the classes
"""

from io import StringIO

from PyQt5 import QtWidgets
from PyQt5.uic.Compiler import compiler


[docs] def loadUiType(uifile, from_imports=False, resource_suffix='_rc', import_from='.', patch_parent_class='', replace_pairs=None): """ loadUiType(uifile, from_imports=False, resource_suffix='_rc', import_from='.') -> (form class, base class) Load a Qt Designer .ui file and return the generated form class and the Qt base class. uifile is a file name or file-like object containing the .ui file. from_imports is optionally set to generate relative import statements. At the moment this only applies to the import of resource modules. resource_suffix is the suffix appended to the basename of any resource file specified in the .ui file to create the name of the Python module generated from the resource file by pyrcc4. The default is '_rc', i.e. if the .ui file specified a resource file called foo.qrc then the corresponding Python module is foo_rc. import_from is optionally set to the package used for relative import statements. The default is ``'.'``. """ code_string = StringIO() winfo = compiler.UICompiler().compileUi(uifile, code_string, from_imports, resource_suffix, import_from) ui_globals = {} if patch_parent_class: winfo['baseclass'] = patch_parent_class cls_list = code_string.getvalue().splitlines() class_import = 'from PyQt5.QtWidgets import {}'.format(patch_parent_class) cls_list.insert(0, class_import) parent_name = None for i, ln in enumerate(cls_list): if ln.startswith('class'): ln = ln.replace('object', patch_parent_class) elif 'setupUi' in ln: parent_name = ln.split(',')[-1].strip(' ):') ln = ' def setupUi(self):' # elif parent_name is not None and ln.strip().startswith(parent_name): elif parent_name is not None: if f'({parent_name})' in ln: # Parent class as arg ln = ln.replace(parent_name, 'self') if f'{parent_name}.' in ln: # Call to parent method # if f'{parent_name}.setObjectName' not in ln: ln = 'remove_me' # TODO: find better keyword # continue if replace_pairs is not None: for pair in replace_pairs: old, new = pair if old in ln: ln = ln.replace(old, new) cls_list[i] = ln cls_list = [ln for ln in cls_list if ln != 'remove_me'] code_string = '\n'.join(cls_list) else: code_string = code_string.getvalue() exec(code_string, ui_globals) return ui_globals[winfo["uiclass"]], getattr(QtWidgets, winfo["baseclass"])