Spaces:
Running
Running
| # Copyright (c) 2023 Riverbank Computing Limited. | |
| # Copyright (c) 2006 Thorsten Marek. | |
| # All right reserved. | |
| # | |
| # This file is part of PyQt. | |
| # | |
| # You may use this file under the terms of the GPL v3 or the revised BSD | |
| # license as follows: | |
| # | |
| # "Redistribution and use in source and binary forms, with or without | |
| # modification, are permitted provided that the following conditions are | |
| # met: | |
| # * Redistributions of source code must retain the above copyright | |
| # notice, this list of conditions and the following disclaimer. | |
| # * Redistributions in binary form must reproduce the above copyright | |
| # notice, this list of conditions and the following disclaimer in | |
| # the documentation and/or other materials provided with the | |
| # distribution. | |
| # * Neither the name of the Riverbank Computing Limited nor the names | |
| # of its contributors may be used to endorse or promote products | |
| # derived from this software without specific prior written | |
| # permission. | |
| # | |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | |
| from .Compiler import indenter, compiler | |
| _header = """# Form implementation generated from reading ui file '{}' | |
| # | |
| # Created by: PyQt6 UI code generator {} | |
| # | |
| # WARNING: Any manual changes made to this file will be lost when pyuic6 is | |
| # run again. Do not edit this file unless you know what you are doing. | |
| """ | |
| _display_code = """ | |
| if __name__ == "__main__": | |
| import sys | |
| app = QtWidgets.QApplication(sys.argv) | |
| %(widgetname)s = QtWidgets.%(baseclass)s() | |
| ui = %(uiclass)s() | |
| ui.setupUi(%(widgetname)s) | |
| %(widgetname)s.show() | |
| sys.exit(app.exec())""" | |
| def compileUiDir(dir, recurse=False, map=None, max_workers=0, **compileUi_args): | |
| """compileUiDir(dir, recurse=False, map=None, **compileUi_args) | |
| Creates Python modules from Qt Designer .ui files in a directory or | |
| directory tree. | |
| dir is the name of the directory to scan for files whose name ends with | |
| '.ui'. By default the generated Python module is created in the same | |
| directory ending with '.py'. | |
| recurse is set if any sub-directories should be scanned. The default is | |
| False. | |
| map is an optional callable that is passed the name of the directory | |
| containing the '.ui' file and the name of the Python module that will be | |
| created. The callable should return a tuple of the name of the directory | |
| in which the Python module will be created and the (possibly modified) | |
| name of the module. The default is None. | |
| max_workers is the maximum number of worker processes to use. A value of 0 | |
| means only the current process is used. A value of None means that the | |
| number of processors on the machine is used. | |
| compileUi_args are any additional keyword arguments that are passed to | |
| the compileUi() function that is called to create each Python module. | |
| """ | |
| from functools import partial | |
| import os | |
| jobs = [] | |
| # Add a compilation job. | |
| def add_job(ui_dir, ui_file): | |
| # Ignore if it doesn't seem to be a .ui file. | |
| if ui_file.endswith('.ui'): | |
| py_dir = ui_dir | |
| py_file = ui_file[:-3] + '.py' | |
| # Allow the caller to change the name of the .py file or generate | |
| # it in a different directory. | |
| if map is not None: | |
| py_dir, py_file = map(py_dir, py_file) | |
| ui_path = os.path.join(ui_dir, ui_file) | |
| jobs.append((ui_path, py_dir, py_file)) | |
| if recurse: | |
| for root, _, files in os.walk(dir): | |
| for ui in files: | |
| add_job(root, ui) | |
| else: | |
| for ui in os.listdir(dir): | |
| if os.path.isfile(os.path.join(dir, ui)): | |
| add_job(dir, ui) | |
| if jobs and max_workers != 0: | |
| from concurrent.futures import ProcessPoolExecutor | |
| with ProcessPoolExecutor(max_workers=max_workers) as executor: | |
| executor.map(partial(_run_job, **compileUi_args), jobs) | |
| else: | |
| for job in jobs: | |
| _run_job(job, **compileUi_args) | |
| def _run_job(job, **compileUi_args): | |
| """ Run a job to compile a single .ui file. """ | |
| import os | |
| ui_path, py_dir, py_file = job | |
| # Make sure the destination directory exists. | |
| try: | |
| os.makedirs(py_dir) | |
| except: | |
| pass | |
| py_path = os.path.join(py_dir, py_file) | |
| with open(py_path, 'w', encoding='utf-8') as py_f: | |
| compileUi(ui_path, py_f, **compileUi_args) | |
| def compileUi(uifile, pyfile, execute=False, indent=4): | |
| """compileUi(uifile, pyfile, execute=False, indent=4) | |
| Creates a Python module from a Qt Designer .ui file. | |
| uifile is a file name or file-like object containing the .ui file. | |
| pyfile is the file-like object to which the Python code will be written to. | |
| execute is optionally set to generate extra Python code that allows the | |
| code to be run as a standalone application. The default is False. | |
| indent is the optional indentation width using spaces. If it is 0 then a | |
| tab is used. The default is 4. | |
| """ | |
| from PyQt6.QtCore import PYQT_VERSION_STR | |
| try: | |
| uifname = uifile.name | |
| except AttributeError: | |
| uifname = uifile | |
| indenter.indentwidth = indent | |
| pyfile.write(_header.format(uifname, PYQT_VERSION_STR)) | |
| winfo = compiler.UICompiler().compileUi(uifile, pyfile) | |
| if execute: | |
| indenter.write_code(_display_code % winfo) | |