ui_file.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  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. from xml.etree import ElementTree
  18. class UIFile:
  19. """ Encapsulate a Designer .ui file. """
  20. def __init__(self, ui_file):
  21. """ Initialise the .ui file. """
  22. # Get the name of the .ui file allowing it to be a file object.
  23. if hasattr(ui_file, 'read'):
  24. self._ui_file = getattr(ui_file, 'name', "unknown")
  25. else:
  26. self._ui_file = ui_file
  27. try:
  28. document = ElementTree.parse(ui_file)
  29. except Exception as e:
  30. self._raise_exception("invalid Qt Designer file", detail=str(e))
  31. # Perform some sanity checks.
  32. root = document.getroot()
  33. if root.tag != 'ui':
  34. self._raise_exception("not created by Qt Designer")
  35. version = root.get('version')
  36. if version is None:
  37. self._raise_exception("missing version number")
  38. if version != '4.0':
  39. self._raise_exception("only Qt Designer files v4.0 are supported")
  40. # Extract the top-level elements.
  41. self.button_groups = None
  42. self.connections = None
  43. self.custom_widgets = None
  44. self.layout_default = None
  45. self.tab_stops = None
  46. self.widget = None
  47. self.class_name = None
  48. for el in root:
  49. if el.tag == 'class':
  50. self.class_name = el.text
  51. elif el.tag == 'buttongroups':
  52. self.button_groups = el
  53. elif el.tag == 'connections':
  54. self.connections = el
  55. elif el.tag == 'customwidgets':
  56. self.custom_widgets = el
  57. elif el.tag == 'layoutdefault':
  58. self.layout_default = el
  59. elif el.tag == 'tabstops':
  60. self.tab_stops = el
  61. elif el.tag == 'widget':
  62. self.widget = el
  63. # The <class> element was optional in legacy versions of the schema.
  64. if not self.class_name:
  65. if self.widget is not None:
  66. self.class_name = self.widget.get('name')
  67. if not self.class_name:
  68. self._raise_exception(
  69. "unable to determine the name of the UI class")
  70. def _raise_exception(self, message, detail=''):
  71. """ Raise a UIFileException. """
  72. from .exceptions import UIFileException
  73. raise UIFileException(self._ui_file, message, detail=detail)