pyuic.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. # Copyright (c) 2026 Riverbank Computing Limited <info@riverbankcomputing.com>
  2. #
  3. # This file is part of PyQt6.
  4. #
  5. # This file may be used under the terms of the GNU General Public License
  6. # version 3.0 as published by the Free Software Foundation and appearing in
  7. # the file LICENSE included in the packaging of this file. Please review the
  8. # following information to ensure the GNU General Public License version 3.0
  9. # requirements will be met: http://www.gnu.org/copyleft/gpl.html.
  10. #
  11. # If you do not wish to use this file under the terms of the GPL version 3.0
  12. # then you may purchase a commercial license. For more information contact
  13. # info@riverbankcomputing.com.
  14. #
  15. # This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
  16. # WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  17. import os
  18. import sys
  19. def main():
  20. """ Convert a .ui file to a .py file. """
  21. import argparse
  22. from PyQt6.QtCore import PYQT_VERSION_STR
  23. from .exceptions import (NoSuchClassError, NoSuchWidgetError,
  24. UIFileException)
  25. # The program name.
  26. PROGRAM_NAME = 'pyuic6'
  27. # Parse the command line.
  28. parser = argparse.ArgumentParser(prog=PROGRAM_NAME,
  29. description="Python User Interface Compiler")
  30. parser.add_argument('-V', '--version', action='version',
  31. version=PYQT_VERSION_STR)
  32. parser.add_argument('-p', '--preview', dest='preview', action='store_true',
  33. default=False,
  34. help="show a preview of the UI instead of generating code")
  35. parser.add_argument('-o', '--output', dest='output', default='-',
  36. metavar="FILE",
  37. help="write generated code to FILE instead of stdout")
  38. parser.add_argument('-x', '--execute', dest='execute', action='store_true',
  39. default=False,
  40. help="generate extra code to test and display the class")
  41. parser.add_argument('-d', '--debug', dest='debug', action='store_true',
  42. default=False, help="show debug output")
  43. parser.add_argument('-i', '--indent', dest='indent', action='store',
  44. type=int, default=4, metavar="N",
  45. help="set indent width to N spaces, tab if N is 0 [default: 4]")
  46. parser.add_argument('-w', '--max-workers', dest='max_workers',
  47. action='store', type=int, default=0, metavar="N",
  48. help="use a maximum of N worker processes when converting a directory [default: 0]")
  49. parser.add_argument('ui',
  50. help="the .ui file created by Qt Designer or a directory containing .ui files")
  51. args = parser.parse_args()
  52. # Carry out the required action.
  53. if args.debug:
  54. configure_logging()
  55. exit_status = 1
  56. try:
  57. if args.preview:
  58. if os.path.isfile(args.ui):
  59. exit_status = preview(args.ui)
  60. else:
  61. raise UIFileException(args.ui, "must be a file")
  62. else:
  63. generate(args.ui, args.output, args.indent, args.execute,
  64. args.max_workers)
  65. exit_status = 0
  66. except IOError as e:
  67. print("Error: {0}: '{1}'".format(e.strerror, e.filename),
  68. file=sys.stderr)
  69. except SyntaxError as e:
  70. print("Error in input file: {0}".format(e), file=sys.stderr)
  71. except (NoSuchClassError, NoSuchWidgetError, UIFileException) as e:
  72. print(e, file=sys.stderr)
  73. except Exception as e:
  74. if args.debug:
  75. import traceback
  76. traceback.print_exception(*sys.exc_info())
  77. else:
  78. print("""An unexpected error occurred.
  79. Check that you are using the latest version of {name} and send an error report
  80. to the PyQt mailing list and include the following information:
  81. - your version of {name} ({version})
  82. - the .ui file that caused this error
  83. - the debug output of {name} (use the --debug flag when calling {name})""".format(name=PROGRAM_NAME, version=PYQT_VERSION_STR), file=sys.stderr)
  84. return exit_status
  85. def configure_logging():
  86. """ Configure logging when debug is enabled. """
  87. import logging
  88. handler = logging.StreamHandler()
  89. handler.setFormatter(logging.Formatter("%(name)s: %(message)s"))
  90. logger = logging.getLogger('PyQt6.uic')
  91. logger.addHandler(handler)
  92. logger.setLevel(logging.DEBUG)
  93. def generate(ui_file, output, indent, execute, max_workers):
  94. """ Generate the Python code. """
  95. from .exceptions import UIFileException
  96. if os.path.isdir(ui_file):
  97. if output == '-':
  98. map = None
  99. elif os.path.isdir(output) or not os.path.exists(output):
  100. map = lambda d, f: (output, f)
  101. else:
  102. raise UIFileException(output,
  103. f"must be a directory as {ui_file} is a directory")
  104. from .compile_ui import compileUiDir
  105. compileUiDir(ui_file, recurse=False, map=map, max_workers=max_workers,
  106. indent=indent, execute=execute)
  107. elif os.path.isdir(output):
  108. raise UIFileException(output,
  109. f"cannot be a directory unless {ui_file} is a directory")
  110. else:
  111. from .compile_ui import compileUi
  112. if output == '-':
  113. import io
  114. pyfile = io.TextIOWrapper(sys.stdout.buffer, encoding='utf8')
  115. needs_close = False
  116. else:
  117. pyfile = open(output, 'wt', encoding='utf8')
  118. needs_close = True
  119. compileUi(ui_file, pyfile, execute, indent)
  120. if needs_close:
  121. pyfile.close()
  122. def preview(ui_file):
  123. """ Preview the .ui file. Return the exit status to be passed back to the
  124. parent process.
  125. """
  126. from PyQt6.QtWidgets import QApplication
  127. from .load_ui import loadUi
  128. app = QApplication([ui_file])
  129. ui = loadUi(ui_file)
  130. ui.show()
  131. return app.exec()
  132. if __name__ == '__main__':
  133. sys.exit(main())