From 48bd6fb47d29ce7a5129761e616e891bc7ad7c3b Mon Sep 17 00:00:00 2001 From: Alex Huszagh Date: Tue, 3 May 2022 12:43:49 -0500 Subject: [PATCH] Refactor examples. Add shared code between the examples, to reduce the amount of boilerplate used in each example. Includes shared colors, Qt5/Qt6 compat definitions, argparsers, and app startup/exec code. --- ISSUES.md | 13 +- example/advanced-dock.py | 127 +------- example/dial.py | 177 ++--------- example/placeholder_text.py | 122 +------- example/shared.py | 600 ++++++++++++++++++++++++++++++++++++ example/slider.py | 160 ++-------- example/standard_icons.py | 410 ++---------------------- example/widgets.py | 216 +++---------- 8 files changed, 736 insertions(+), 1089 deletions(-) create mode 100644 example/shared.py diff --git a/ISSUES.md b/ISSUES.md index 8082921..a4fb614 100644 --- a/ISSUES.md +++ b/ISSUES.md @@ -223,12 +223,6 @@ class ApplicationStyle(QtWidgets.QCommonStyle): def main(): app = QtWidgets.QApplication(sys.argv) - # Set our stylesheet. - file = QtCore.QFile('dark:stylesheet.qss') - file.open(OpenModeFlag.ReadOnly | OpenModeFlag.Text) - stream = QtCore.QTextStream(file) - app.setStyleSheet(stream.readAll()) - # Install our custom style globally. QCommonStyle, unlike QProxyStyle, # actually works nicely with stylesheets. `Fusion` is available # on all platforms, but you can use any style you want. We @@ -237,6 +231,13 @@ def main(): style = QtWidgets.QStyleFactory.create('Fusion') app.setStyle(ApplicationStyle(style)) + # Set our stylesheet. + # NOTE: this must occur after setting the application style. + file = QtCore.QFile('dark:stylesheet.qss') + file.open(OpenModeFlag.ReadOnly | OpenModeFlag.Text) + stream = QtCore.QTextStream(file) + app.setStyleSheet(stream.readAll()) + ... return app.exec() diff --git a/example/advanced-dock.py b/example/advanced-dock.py index dd73152..cd18a79 100644 --- a/example/advanced-dock.py +++ b/example/advanced-dock.py @@ -29,125 +29,26 @@ Simple PyQt application using the advanced-docking-system. ''' -import argparse -import os +import shared import sys -example_dir = os.path.dirname(os.path.realpath(__file__)) -home = os.path.dirname(example_dir) -dist = os.path.join(home, 'dist') - -# Create our arguments. -parser = argparse.ArgumentParser(description='Configurations for the Qt5 application.') -parser.add_argument( - '--stylesheet', - help='''stylesheet name''', - default='native' -) -# Know working styles include: -# 1. Fusion -# 2. Windows -parser.add_argument( - '--style', - help='''application style, which is different than the stylesheet''', - default='native' -) -parser.add_argument( - '--font-size', - help='''font size for the application''', - type=float, - default=-1 -) -parser.add_argument( - '--font-family', - help='''the font family''' -) -parser.add_argument( - '--scale', - help='''scale factor for the UI''', - type=float, - default=1, -) -parser.add_argument( - '--pyqt6', - help='''use PyQt6 rather than PyQt5.''', - action='store_true' -) +parser = shared.create_parser() parser.add_argument( '--use-internal', help='''use the dock manager internal stylesheet.''', action='store_true' ) -parser.add_argument( - '--use-x11', - help='''force the use of x11 on compatible systems.''', - action='store_true' -) - -args, unknown = parser.parse_known_args() -if args.pyqt6: - from PyQt6 import QtCore, QtGui, QtWidgets - QtCore.QDir.addSearchPath(args.stylesheet, f'{dist}/pyqt6/{args.stylesheet}/') - resource_format = f'{args.stylesheet}:' -else: - sys.path.insert(0, home) - from PyQt5 import QtCore, QtGui, QtWidgets - import breeze_resources - resource_format = f':/{args.stylesheet}/' -stylesheet = f'{resource_format}stylesheet.qss' +args, unknown = shared.parse_args(parser) +QtCore, QtGui, QtWidgets = shared.import_qt(args) +compat = shared.get_compat_definitions(args) from PyQtAds import QtAds -# Compat definitions, between Qt5 and Qt6. -if args.pyqt6: - AlignTop = QtCore.Qt.AlignmentFlag.AlignTop - AlignLeft = QtCore.Qt.AlignmentFlag.AlignLeft - ReadOnly = QtCore.QFile.OpenModeFlag.ReadOnly - Text = QtCore.QFile.OpenModeFlag.Text - WindowMaximized = QtCore.Qt.WindowState.WindowMaximized -else: - AlignTop = QtCore.Qt.AlignTop - AlignLeft = QtCore.Qt.AlignLeft - ReadOnly = QtCore.QFile.ReadOnly - Text = QtCore.QFile.Text - WindowMaximized = QtCore.Qt.WindowMaximized - -# Need to fix an issue on Wayland on Linux: -# conda-forge does not support Wayland, for who knows what reason. -if sys.platform.lower().startswith('linux') and 'CONDA_PREFIX' in os.environ: - args.use_x11 = True - -if args.use_x11: - os.environ['XDG_SESSION_TYPE'] = 'x11' def main(): 'Application entry point' - if args.scale != 1: - os.environ['QT_SCALE_FACTOR'] = str(args.scale) - else: - os.environ['QT_AUTO_SCREEN_SCALE_FACTOR'] = '1' - app = QtWidgets.QApplication(sys.argv[:1] + unknown) - if args.style != 'native': - style = QtWidgets.QStyleFactory.create(args.style) - app.setStyle(style) - - window = QtWidgets.QMainWindow() - - # use the default font size - font = app.font() - if args.font_size > 0: - font.setPointSizeF(args.font_size) - if args.font_family: - font.setFamily(args.font_family) - app.setFont(font) - - # setup stylesheet - if args.stylesheet != 'native': - file = QtCore.QFile(stylesheet) - file.open(ReadOnly | Text) - stream = QtCore.QTextStream(file) - app.setStyleSheet(stream.readAll()) + app, window = shared.setup_app(args, unknown, compat) # setup the dock manager window.setObjectName('MainWindow') @@ -156,12 +57,14 @@ def main(): window.setCentralWidget(widget) dock_manager = QtAds.CDockManager(window) + DockArea = QtAds.DockWidgetArea + # add widgets to the dock manager label_widget = QtAds.CDockWidget('Dock') label = QtWidgets.QLabel('Some label') label_widget.setWidget(label) dock_area = dock_manager.setCentralWidget(label_widget) - dock_area.setAllowedAreas(QtAds.DockWidgetArea.OuterDockAreas) + dock_area.setAllowedAreas(DockArea.OuterDockAreas) list_widget = QtAds.CDockWidget('List') lst = QtWidgets.QListWidget() @@ -169,7 +72,7 @@ def main(): lst.addItem(QtWidgets.QListWidgetItem(f'Item {index + 1}')) list_widget.setWidget(lst) list_widget.setMinimumSizeHintMode(QtAds.CDockWidget.MinimumSizeHintFromDockWidget) - dock_manager.addDockWidget(QtAds.DockWidgetArea.LeftDockWidgetArea, list_widget, dock_area) + dock_manager.addDockWidget(DockArea.LeftDockWidgetArea, list_widget, dock_area) table_widget = QtAds.CDockWidget('Table') table = QtWidgets.QTableWidget() @@ -178,18 +81,14 @@ def main(): table.setRowCount(40) table_widget.setWidget(table) table_widget.setMinimumSizeHintMode(QtAds.CDockWidget.MinimumSizeHintFromDockWidget) - dock_manager.addDockWidget(QtAds.DockWidgetArea.RightDockWidgetArea, table_widget, dock_area) + dock_manager.addDockWidget(DockArea.RightDockWidgetArea, table_widget, dock_area) if not args.use_internal: dock_manager.setStyleSheet('') # run - window.setWindowState(WindowMaximized) - window.show() - if args.pyqt6: - return app.exec() - else: - return app.exec_() + window.setWindowState(compat.WindowMaximized) + return shared.exec_app(args, app, window, compat) if __name__ == '__main__': sys.exit(main()) diff --git a/example/dial.py b/example/dial.py index ade548d..c0f26b7 100644 --- a/example/dial.py +++ b/example/dial.py @@ -31,123 +31,20 @@ supports highlighting the handle on the active or hovered dial. ''' -import argparse import math -import os +import shared import sys -example_dir = os.path.dirname(os.path.realpath(__file__)) -home = os.path.dirname(example_dir) -dist = os.path.join(home, 'dist') - -# Create our arguments. -parser = argparse.ArgumentParser(description='Configurations for the Qt5 application.') -parser.add_argument( - '--stylesheet', - help='''stylesheet name''', - default='native' -) -# Know working styles include: -# 1. Fusion -# 2. Windows -parser.add_argument( - '--style', - help='''application style, which is different than the stylesheet''', - default='native' -) -parser.add_argument( - '--font-size', - help='''font size for the application''', - type=float, - default=-1 -) -parser.add_argument( - '--font-family', - help='''the font family''' -) -parser.add_argument( - '--scale', - help='''scale factor for the UI''', - type=float, - default=1, -) -parser.add_argument( - '--pyqt6', - help='''use PyQt6 rather than PyQt5.''', - action='store_true' -) -parser.add_argument( - '--use-x11', - help='''force the use of x11 on compatible systems.''', - action='store_true' -) +parser = shared.create_parser() parser.add_argument( '--no-align', help='''allow larger widgets without forcing alignment.''', action='store_true' ) - -args, unknown = parser.parse_known_args() -if args.pyqt6: - from PyQt6 import QtCore, QtGui, QtWidgets - QtCore.QDir.addSearchPath(args.stylesheet, f'{dist}/pyqt6/{args.stylesheet}/') - resource_format = f'{args.stylesheet}:' -else: - sys.path.insert(0, home) - from PyQt5 import QtCore, QtGui, QtWidgets - import breeze_resources - resource_format = f':/{args.stylesheet}/' -stylesheet = f'{resource_format}stylesheet.qss' - -# Compat definitions, between Qt5 and Qt6. -if args.pyqt6: - AlignHCenter = QtCore.Qt.AlignmentFlag.AlignHCenter - ReadOnly = QtCore.QFile.OpenModeFlag.ReadOnly - Text = QtCore.QFile.OpenModeFlag.Text - SolidLine = QtCore.Qt.PenStyle.SolidLine - FlatCap = QtCore.Qt.PenCapStyle.FlatCap - SquareCap = QtCore.Qt.PenCapStyle.SquareCap - RoundCap = QtCore.Qt.PenCapStyle.RoundCap - MiterJoin = QtCore.Qt.PenJoinStyle.MiterJoin - BevelJoin = QtCore.Qt.PenJoinStyle.BevelJoin - RoundJoin = QtCore.Qt.PenJoinStyle.RoundJoin - SvgMiterJoin = QtCore.Qt.PenJoinStyle.SvgMiterJoin - State_HasFocus = QtWidgets.QStyle.StateFlag.State_HasFocus - State_Selected = QtWidgets.QStyle.StateFlag.State_Selected - HoverEnter = QtCore.QEvent.Type.HoverEnter - HoverMove = QtCore.QEvent.Type.HoverMove - HoverLeave = QtCore.QEvent.Type.HoverLeave -else: - AlignHCenter = QtCore.Qt.AlignHCenter - ReadOnly = QtCore.QFile.ReadOnly - Text = QtCore.QFile.Text - SolidLine = QtCore.Qt.SolidLine - FlatCap = QtCore.Qt.FlatCap - SquareCap = QtCore.Qt.SquareCap - RoundCap = QtCore.Qt.RoundCap - MiterJoin = QtCore.Qt.MiterJoin - BevelJoin = QtCore.Qt.BevelJoin - RoundJoin = QtCore.Qt.RoundJoin - SvgMiterJoin = QtCore.Qt.SvgMiterJoin - State_HasFocus = QtWidgets.QStyle.State_HasFocus - State_Selected = QtWidgets.QStyle.State_Selected - HoverEnter = QtCore.QEvent.HoverEnter - HoverMove = QtCore.QEvent.HoverMove - HoverLeave = QtCore.QEvent.HoverLeave - -SELECTED = QtGui.QColor(61, 174, 233) -if 'dark' in args.stylesheet: - GROOVE_BACKGROUND = QtGui.QColor(98, 101, 104) - GROOVE_BORDER = QtGui.QColor(49, 54, 59) - HANDLE_BACKGROUND = QtGui.QColor(29, 32, 35) - HANDLE_BORDER = QtGui.QColor(98, 101, 104) - NOTCH = QtGui.QColor(51, 78, 94) -elif 'light' in args.stylesheet: - GROOVE_BACKGROUND = QtGui.QColor(106, 105, 105, 179) - GROOVE_BORDER = QtGui.QColor(239, 240, 241) - HANDLE_BACKGROUND = QtGui.QColor(239, 240, 241) - HANDLE_BORDER = QtGui.QColor(106, 105, 105, 179) - NOTCH = QtGui.QColor(61, 173, 232, 51) +args, unknown = shared.parse_args(parser) +QtCore, QtGui, QtWidgets = shared.import_qt(args) +compat = shared.get_compat_definitions(args) +colors = shared.get_colors(args, compat) def radius(dial): @@ -209,7 +106,13 @@ def default_pen(color, width): def round_pen(color, width): '''Create a pen with round join styles.''' - return QtGui.QPen(color, width, SolidLine, RoundCap, RoundJoin) + return QtGui.QPen( + color, + width, + compat.SolidLine, + compat.RoundCap, + compat.RoundJoin, + ) def event_pos(event): '''Determine the event position.''' @@ -238,12 +141,12 @@ class Dial(QtWidgets.QDial): self.notch_start = self.groove_width + 2 self.notch_end = self.notch_start + 2 self.notch_width = 2 - self.groove_bd_color = GROOVE_BORDER - self.groove_bg_color = GROOVE_BACKGROUND - self.handle_bg_color = HANDLE_BACKGROUND - self.handle_bd_color = HANDLE_BORDER - self.notch_color = NOTCH - self.selected_color = SELECTED + self.groove_bd_color = colors.GrooveBorder + self.groove_bg_color = colors.GrooveBackground + self.handle_bg_color = colors.HandleBackground + self.handle_bd_color = colors.HandleBorder + self.notch_color = colors.Notch + self.selected_color = colors.Selected # Store some state changes. self.groove = (0, 0) @@ -262,7 +165,7 @@ class Dial(QtWidgets.QDial): # Get our item colors. Override the color when selected/active. handle_bd_color = self.handle_bd_color - mask = State_HasFocus | State_Selected + mask = compat.State_HasFocus | compat.State_Selected # WindowActive if options.state & mask or self.is_hovered: handle_bd_color = self.selected_color @@ -347,14 +250,14 @@ class Dial(QtWidgets.QDial): # for the handle, and determine if the mouse is contained in there, # rather than calculate if it's actually in the circle. This won't # matter except if the dial is scaled by a large amount. - if event.type() == HoverEnter or event.type() == HoverMove: + if event.type() == compat.HoverEnter or event.type() == compat.HoverMove: x0 = self.handle[0] - self.handle_radius y0 = self.handle[1] - self.handle_radius size = 2 * self.handle_radius rect = QtCore.QRectF(x0, y0, size, size) self.is_hovered = rect.contains(event_pos(event)) self.repaint() - elif event.type() == HoverLeave: + elif event.type() == compat.HoverLeave: self.is_hovered = False self.repaint() @@ -372,7 +275,7 @@ class Ui: self.layout = QtWidgets.QVBoxLayout(self.centralwidget) self.layout.setObjectName('layout') if not args.no_align: - self.layout.setAlignment(AlignHCenter) + self.layout.setAlignment(compat.AlignHCenter) MainWindow.setCentralWidget(self.centralwidget) self.dial1 = Dial(self.centralwidget) @@ -390,44 +293,14 @@ class Ui: def main(): 'Application entry point' - if args.scale != 1: - os.environ['QT_SCALE_FACTOR'] = str(args.scale) - else: - os.environ['QT_AUTO_SCREEN_SCALE_FACTOR'] = '1' - - app = QtWidgets.QApplication(sys.argv[:1] + unknown) - if args.style != 'native': - style = QtWidgets.QStyleFactory.create(args.style) - app.setStyle(style) - - window = QtWidgets.QMainWindow() + app, window = shared.setup_app(args, unknown, compat) # setup ui ui = Ui() ui.setup(window) window.setWindowTitle('QDial') - # use the default font size - font = app.font() - if args.font_size > 0: - font.setPointSizeF(args.font_size) - if args.font_family: - font.setFamily(args.font_family) - app.setFont(font) - - # setup stylesheet - if args.stylesheet != 'native': - file = QtCore.QFile(stylesheet) - file.open(ReadOnly | Text) - stream = QtCore.QTextStream(file) - app.setStyleSheet(stream.readAll()) - - # run - window.show() - if args.pyqt6: - return app.exec() - else: - return app.exec_() + return shared.exec_app(args, app, window, compat) if __name__ == '__main__': sys.exit(main()) diff --git a/example/placeholder_text.py b/example/placeholder_text.py index 2a5d8f4..26c32d0 100644 --- a/example/placeholder_text.py +++ b/example/placeholder_text.py @@ -33,55 +33,10 @@ and palette edits correctly affect styles in Qt5, but not Qt6. ''' -import argparse -import os +import shared import sys -example_dir = os.path.dirname(os.path.realpath(__file__)) -home = os.path.dirname(example_dir) -dist = os.path.join(home, 'dist') - -# Create our arguments. -parser = argparse.ArgumentParser(description='Configurations for the Qt5 application.') -parser.add_argument( - '--stylesheet', - help='''stylesheet name''', - default='native' -) -# Know working styles include: -# 1. Fusion -# 2. Windows -parser.add_argument( - '--style', - help='''application style, which is different than the stylesheet''', - default='native' -) -parser.add_argument( - '--font-size', - help='''font size for the application''', - type=float, - default=-1 -) -parser.add_argument( - '--font-family', - help='''the font family''' -) -parser.add_argument( - '--scale', - help='''scale factor for the UI''', - type=float, - default=1, -) -parser.add_argument( - '--pyqt6', - help='''use PyQt6 rather than PyQt5.''', - action='store_true' -) -parser.add_argument( - '--use-x11', - help='''force the use of x11 on compatible systems.''', - action='store_true' -) +parser = shared.create_parser() parser.add_argument( '--set-app-palette', help='''set the placeholder text palette globally.''', @@ -92,38 +47,11 @@ parser.add_argument( help='''set the placeholder text palette for the affected widgets.''', action='store_true' ) +args, unknown = shared.parse_args(parser) +QtCore, QtGui, QtWidgets = shared.import_qt(args) +compat = shared.get_compat_definitions(args) +colors = shared.get_colors(args, compat) -args, unknown = parser.parse_known_args() -if args.pyqt6: - from PyQt6 import QtCore, QtGui, QtWidgets - QtCore.QDir.addSearchPath(args.stylesheet, f'{dist}/pyqt6/{args.stylesheet}/') - resource_format = f'{args.stylesheet}:' -else: - sys.path.insert(0, home) - from PyQt5 import QtCore, QtGui, QtWidgets - import breeze_resources - resource_format = f':/{args.stylesheet}/' -stylesheet = f'{resource_format}stylesheet.qss' - -# Compat definitions, between Qt5 and Qt6. -if args.pyqt6: - AlignHCenter = QtCore.Qt.AlignmentFlag.AlignHCenter - ReadOnly = QtCore.QFile.OpenModeFlag.ReadOnly - Text = QtCore.QFile.OpenModeFlag.Text - PlaceholderText = QtGui.QPalette.ColorRole.PlaceholderText - WindowText = QtGui.QPalette.ColorRole.WindowText -else: - AlignHCenter = QtCore.Qt.AlignHCenter - ReadOnly = QtCore.QFile.ReadOnly - Text = QtCore.QFile.Text - PlaceholderText = QtGui.QPalette.PlaceholderText - WindowText = QtGui.QPalette.WindowText - -PLACEHOLDER_COLOR = QtGui.QColor(255, 0, 0) -if 'dark' in args.stylesheet: - PLACEHOLDER_COLOR = QtGui.QColor(118, 121, 124) -elif 'light' in args.stylesheet: - PLACEHOLDER_COLOR = QtGui.QColor(186, 185, 184) def set_palette(widget, role, color): '''Set the palette for the placeholder text. This only works in Qt5.''' @@ -133,7 +61,7 @@ def set_palette(widget, role, color): widget.setPalette(palette) def set_placeholder_palette(widget): - set_palette(widget, PlaceholderText, PLACEHOLDER_COLOR) + set_palette(widget, compat.PlaceholderText, colors.PlaceholderColor) class Ui: @@ -146,7 +74,7 @@ class Ui: self.centralwidget.setObjectName('centralwidget') self.layout = QtWidgets.QVBoxLayout(self.centralwidget) self.layout.setObjectName('layout') - self.layout.setAlignment(AlignHCenter) + self.layout.setAlignment(compat.AlignHCenter) MainWindow.setCentralWidget(self.centralwidget) self.textEdit = QtWidgets.QTextEdit(self.centralwidget) @@ -172,46 +100,16 @@ class Ui: def main(): 'Application entry point' - if args.scale != 1: - os.environ['QT_SCALE_FACTOR'] = str(args.scale) - else: - os.environ['QT_AUTO_SCREEN_SCALE_FACTOR'] = '1' - - app = QtWidgets.QApplication(sys.argv[:1] + unknown) - if args.style != 'native': - style = QtWidgets.QStyleFactory.create(args.style) - app.setStyle(style) + app, window = shared.setup_app(args, unknown, compat) if args.set_app_palette: set_placeholder_palette(app) - window = QtWidgets.QMainWindow() - # setup ui ui = Ui() ui.setup(window) window.setWindowTitle('Stylized Placeholder Text.') - # use the default font size - font = app.font() - if args.font_size > 0: - font.setPointSizeF(args.font_size) - if args.font_family: - font.setFamily(args.font_family) - app.setFont(font) - - # setup stylesheet - if args.stylesheet != 'native': - file = QtCore.QFile(stylesheet) - file.open(ReadOnly | Text) - stream = QtCore.QTextStream(file) - app.setStyleSheet(stream.readAll()) - - # run - window.show() - if args.pyqt6: - return app.exec() - else: - return app.exec_() + return shared.exec_app(args, app, window, compat) if __name__ == '__main__': sys.exit(main()) diff --git a/example/shared.py b/example/shared.py new file mode 100644 index 0000000..7de86f9 --- /dev/null +++ b/example/shared.py @@ -0,0 +1,600 @@ +''' + shared + ====== + + Shared imports and compatibility definitions between Qt5 and Qt6. +''' + +import argparse +import os +import sys + +example_dir = os.path.dirname(os.path.realpath(__file__)) +home = os.path.dirname(example_dir) +dist = os.path.join(home, 'dist') + +def create_parser(): + '''Create an argparser with the base settings for all Qt applications.''' + + parser = argparse.ArgumentParser( + description='Configurations for the Qt5 application.' + ) + parser.add_argument( + '--stylesheet', + help='''stylesheet name''', + default='native' + ) + # Know working styles include: + # 1. Fusion + # 2. Windows + parser.add_argument( + '--style', + help='''application style, which is different than the stylesheet''', + default='native' + ) + parser.add_argument( + '--font-size', + help='''font size for the application''', + type=float, + default=-1 + ) + parser.add_argument( + '--font-family', + help='''the font family''' + ) + parser.add_argument( + '--scale', + help='''scale factor for the UI''', + type=float, + default=1, + ) + parser.add_argument( + '--pyqt6', + help='''use PyQt6 rather than PyQt5.''', + action='store_true' + ) + # Linux or Unix-like only. + parser.add_argument( + '--use-x11', + help='''force the use of x11 on compatible systems.''', + action='store_true' + ) + + return parser + +def parse_args(parser): + '''Parse the command-line arguments and hot-patch the args.''' + + args, unknown = parser.parse_known_args() + # Need to fix an issue on Wayland on Linux: + # conda-forge does not support Wayland, for who knows what reason. + if sys.platform.lower().startswith('linux') and 'CONDA_PREFIX' in os.environ: + args.use_x11 = True + + if args.use_x11: + os.environ['XDG_SESSION_TYPE'] = 'x11' + + return args, unknown + +def import_qt(args): + '''Import the Qt modules''' + + if args.pyqt6: + from PyQt6 import QtCore, QtGui, QtWidgets + QtCore.QDir.addSearchPath(args.stylesheet, f'{dist}/pyqt6/{args.stylesheet}/') + else: + sys.path.insert(0, home) + from PyQt5 import QtCore, QtGui, QtWidgets + import breeze_resources + + return QtCore, QtGui, QtWidgets + +def get_resources(args): + '''Get the resource format for the Qt application.''' + + if args.pyqt6: + return f'{args.stylesheet}:' + return f':/{args.stylesheet}/' + +def get_stylesheet(resource_format): + '''Get the path to the stylesheet.''' + return f'{resource_format}stylesheet.qss' + +def get_compat_definitions(args): + '''Create our compatibility definitions.''' + + ns = argparse.Namespace() + if args.pyqt6: + from PyQt6 import QtCore, QtGui, QtWidgets + + # Modules + ns.QtCore = QtCore + ns.QtGui = QtGui + ns.QtWidgets = QtWidgets + + # Scoped enums. + ns.Orientation = QtCore.Qt.Orientation + ns.StandardPixmap = QtWidgets.QStyle.StandardPixmap + ns.ToolBarArea = QtCore.Qt.ToolBarArea + ns.FrameShape = QtWidgets.QFrame.Shape + ns.FrameShadow = QtWidgets.QFrame.Shadow + ns.ToolButtonPopupMode = QtWidgets.QToolButton.ToolButtonPopupMode + ns.AlignmentFlag = QtCore.Qt.AlignmentFlag + ns.OpenModeFlag = QtCore.QFile.OpenModeFlag + ns.TabShape = QtWidgets.QTabWidget.TabShape + ns.ItemFlag = QtCore.Qt.ItemFlag + ns.CheckState = QtCore.Qt.CheckState + ns.TabPosition = QtWidgets.QTabWidget.TabPosition + ns.EchoMode = QtWidgets.QLineEdit.EchoMode + ns.ArrowType = QtCore.Qt.ArrowType + ns.WindowState = QtCore.Qt.WindowState + ns.PenStyle = QtCore.Qt.PenStyle + ns.PenCapStyle = QtCore.Qt.PenCapStyle + ns.PenJoinStyle = QtCore.Qt.PenJoinStyle + ns.StateFlag = QtWidgets.QStyle.StateFlag + ns.EventType = QtCore.QEvent.Type + ns.ColorRole = QtGui.QPalette.ColorRole + ns.TickPosition = QtWidgets.QSlider.TickPosition + ns.ComplexControl = QtWidgets.QStyle.ComplexControl + ns.SubControl = QtWidgets.QStyle.SubControl + + # QObjects + ns.QAction = QtGui.QAction + + # Enumerations + ns.Horizontal = ns.Orientation.Horizontal + ns.Vertical = ns.Orientation.Vertical + ns.AlignTop = ns.AlignmentFlag.AlignTop + ns.AlignLeft = ns.AlignmentFlag.AlignLeft + ns.AlignHCenter = ns.AlignmentFlag.AlignHCenter + ns.StyledPanel = ns.FrameShape.StyledPanel + ns.HLine = ns.FrameShape.HLine + ns.VLine = ns.FrameShape.VLine + ns.TopToolBarArea = ns.ToolBarArea.TopToolBarArea + ns.Raised = ns.FrameShadow.Raised + ns.Sunken = ns.FrameShadow.Sunken + ns.InstantPopup = ns.ToolButtonPopupMode.InstantPopup + ns.MenuButtonPopup = ns.ToolButtonPopupMode.MenuButtonPopup + ns.ItemIsUserCheckable = ns.ItemFlag.ItemIsUserCheckable + ns.ItemIsUserTristate = ns.ItemFlag.ItemIsUserTristate + ns.Checked = ns.CheckState.Checked + ns.Unchecked = ns.CheckState.Unchecked + ns.PartiallyChecked = ns.CheckState.PartiallyChecked + ns.ReadOnly = ns.OpenModeFlag.ReadOnly + ns.Text = ns.OpenModeFlag.Text + ns.East = ns.TabPosition.East + ns.UpArrow = ns.ArrowType.UpArrow + ns.Triangular = ns.TabShape.Triangular + ns.Password = ns.EchoMode.Password + ns.WindowMaximized = ns.WindowState.WindowMaximized + ns.SolidLine = ns.PenStyle.SolidLine + ns.FlatCap = ns.PenCapStyle.FlatCap + ns.SquareCap = ns.PenCapStyle.SquareCap + ns.RoundCap = ns.PenCapStyle.RoundCap + ns.MiterJoin = ns.PenJoinStyle.MiterJoin + ns.BevelJoin = ns.PenJoinStyle.BevelJoin + ns.RoundJoin = ns.PenJoinStyle.RoundJoin + ns.SvgMiterJoin = ns.PenJoinStyle.SvgMiterJoin + ns.State_HasFocus = ns.StateFlag.State_HasFocus + ns.State_Selected = ns.StateFlag.State_Selected + ns.HoverEnter = ns.EventType.HoverEnter + ns.HoverMove = ns.EventType.HoverMove + ns.HoverLeave = ns.EventType.HoverLeave + ns.PlaceholderText = ns.ColorRole.PlaceholderText + ns.NoTicks = ns.TickPosition.NoTicks + ns.TicksAbove = ns.TickPosition.TicksAbove + ns.TicksBelow = ns.TickPosition.TicksBelow + ns.TicksBothSides = ns.TickPosition.TicksBothSides + ns.CC_Slider = ns.ComplexControl.CC_Slider + ns.SC_SliderHandle = ns.SubControl.SC_SliderHandle + ns.SC_SliderGroove = ns.SubControl.SC_SliderGroove + ns.SP_ArrowBack = ns.StandardPixmap.SP_ArrowBack + ns.SP_ArrowDown = ns.StandardPixmap.SP_ArrowDown + ns.SP_ArrowForward = ns.StandardPixmap.SP_ArrowForward + ns.SP_ArrowLeft = ns.StandardPixmap.SP_ArrowLeft + ns.SP_ArrowRight = ns.StandardPixmap.SP_ArrowRight + ns.SP_ArrowUp = ns.StandardPixmap.SP_ArrowUp + ns.SP_BrowserReload = ns.StandardPixmap.SP_BrowserReload + ns.SP_BrowserStop = ns.StandardPixmap.SP_BrowserStop + ns.SP_CommandLink = ns.StandardPixmap.SP_CommandLink + ns.SP_ComputerIcon = ns.StandardPixmap.SP_ComputerIcon + ns.SP_CustomBase = ns.StandardPixmap.SP_CustomBase + ns.SP_DesktopIcon = ns.StandardPixmap.SP_DesktopIcon + ns.SP_DialogApplyButton = ns.StandardPixmap.SP_DialogApplyButton + ns.SP_DialogCancelButton = ns.StandardPixmap.SP_DialogCancelButton + ns.SP_DialogCloseButton = ns.StandardPixmap.SP_DialogCloseButton + ns.SP_DialogDiscardButton = ns.StandardPixmap.SP_DialogDiscardButton + ns.SP_DialogHelpButton = ns.StandardPixmap.SP_DialogHelpButton + ns.SP_DialogNoButton = ns.StandardPixmap.SP_DialogNoButton + ns.SP_DialogOkButton = ns.StandardPixmap.SP_DialogOkButton + ns.SP_DialogOpenButton = ns.StandardPixmap.SP_DialogOpenButton + ns.SP_DialogResetButton = ns.StandardPixmap.SP_DialogResetButton + ns.SP_DialogSaveButton = ns.StandardPixmap.SP_DialogSaveButton + ns.SP_DialogYesButton = ns.StandardPixmap.SP_DialogYesButton + ns.SP_DirClosedIcon = ns.StandardPixmap.SP_DirClosedIcon + ns.SP_DirHomeIcon = ns.StandardPixmap.SP_DirHomeIcon + ns.SP_DirIcon = ns.StandardPixmap.SP_DirIcon + ns.SP_DirLinkIcon = ns.StandardPixmap.SP_DirLinkIcon + ns.SP_DirLinkOpenIcon = ns.StandardPixmap.SP_DirLinkOpenIcon + ns.SP_DirOpenIcon = ns.StandardPixmap.SP_DirOpenIcon + ns.SP_DockWidgetCloseButton = ns.StandardPixmap.SP_DockWidgetCloseButton + ns.SP_DriveCDIcon = ns.StandardPixmap.SP_DriveCDIcon + ns.SP_DriveDVDIcon = ns.StandardPixmap.SP_DriveDVDIcon + ns.SP_DriveFDIcon = ns.StandardPixmap.SP_DriveFDIcon + ns.SP_DriveHDIcon = ns.StandardPixmap.SP_DriveHDIcon + ns.SP_DriveNetIcon = ns.StandardPixmap.SP_DriveNetIcon + ns.SP_FileDialogBack = ns.StandardPixmap.SP_FileDialogBack + ns.SP_FileDialogContentsView = ns.StandardPixmap.SP_FileDialogContentsView + ns.SP_FileDialogDetailedView = ns.StandardPixmap.SP_FileDialogDetailedView + ns.SP_FileDialogEnd = ns.StandardPixmap.SP_FileDialogEnd + ns.SP_FileDialogInfoView = ns.StandardPixmap.SP_FileDialogInfoView + ns.SP_FileDialogListView = ns.StandardPixmap.SP_FileDialogListView + ns.SP_FileDialogNewFolder = ns.StandardPixmap.SP_FileDialogNewFolder + ns.SP_FileDialogStart = ns.StandardPixmap.SP_FileDialogStart + ns.SP_FileDialogToParent = ns.StandardPixmap.SP_FileDialogToParent + ns.SP_FileIcon = ns.StandardPixmap.SP_FileIcon + ns.SP_FileLinkIcon = ns.StandardPixmap.SP_FileLinkIcon + ns.SP_MediaPause = ns.StandardPixmap.SP_MediaPause + ns.SP_MediaPlay = ns.StandardPixmap.SP_MediaPlay + ns.SP_MediaSeekBackward = ns.StandardPixmap.SP_MediaSeekBackward + ns.SP_MediaSeekForward = ns.StandardPixmap.SP_MediaSeekForward + ns.SP_MediaSkipBackward = ns.StandardPixmap.SP_MediaSkipBackward + ns.SP_MediaSkipForward = ns.StandardPixmap.SP_MediaSkipForward + ns.SP_MediaStop = ns.StandardPixmap.SP_MediaStop + ns.SP_MediaVolume = ns.StandardPixmap.SP_MediaVolume + ns.SP_MediaVolumeMuted = ns.StandardPixmap.SP_MediaVolumeMuted + ns.SP_LineEditClearButton = ns.StandardPixmap.SP_LineEditClearButton + ns.SP_DialogYesToAllButton = ns.StandardPixmap.SP_DialogYesToAllButton + ns.SP_DialogNoToAllButton = ns.StandardPixmap.SP_DialogNoToAllButton + ns.SP_DialogSaveAllButton = ns.StandardPixmap.SP_DialogSaveAllButton + ns.SP_DialogAbortButton = ns.StandardPixmap.SP_DialogAbortButton + ns.SP_DialogRetryButton = ns.StandardPixmap.SP_DialogRetryButton + ns.SP_DialogIgnoreButton = ns.StandardPixmap.SP_DialogIgnoreButton + ns.SP_RestoreDefaultsButton = ns.StandardPixmap.SP_RestoreDefaultsButton + if QtCore.QT_VERSION >= 393984: + ns.SP_TabCloseButton = ns.StandardPixmap.SP_TabCloseButton + ns.SP_MessageBoxCritical = ns.StandardPixmap.SP_MessageBoxCritical + ns.SP_MessageBoxInformation = ns.StandardPixmap.SP_MessageBoxInformation + ns.SP_MessageBoxQuestion = ns.StandardPixmap.SP_MessageBoxQuestion + ns.SP_MessageBoxWarning = ns.StandardPixmap.SP_MessageBoxWarning + ns.SP_TitleBarCloseButton = ns.StandardPixmap.SP_TitleBarCloseButton + ns.SP_TitleBarContextHelpButton = ns.StandardPixmap.SP_TitleBarContextHelpButton + ns.SP_TitleBarMaxButton = ns.StandardPixmap.SP_TitleBarMaxButton + ns.SP_TitleBarMenuButton = ns.StandardPixmap.SP_TitleBarMenuButton + ns.SP_TitleBarMinButton = ns.StandardPixmap.SP_TitleBarMinButton + ns.SP_TitleBarNormalButton = ns.StandardPixmap.SP_TitleBarNormalButton + ns.SP_TitleBarShadeButton = ns.StandardPixmap.SP_TitleBarShadeButton + ns.SP_TitleBarUnshadeButton = ns.StandardPixmap.SP_TitleBarUnshadeButton + ns.SP_ToolBarHorizontalExtensionButton = ns.StandardPixmap.SP_ToolBarHorizontalExtensionButton + ns.SP_ToolBarVerticalExtensionButton = ns.StandardPixmap.SP_ToolBarVerticalExtensionButton + ns.SP_TrashIcon = ns.StandardPixmap.SP_TrashIcon + ns.SP_VistaShield = ns.StandardPixmap.SP_VistaShield + else: + from PyQt5 import QtCore, QtGui, QtWidgets + + # Modules + ns.QtCore = QtCore + ns.QtGui = QtGui + ns.QtWidgets = QtWidgets + + # QObjects + ns.QAction = QtWidgets.QAction + + # Enumerations + ns.Horizontal = QtCore.Qt.Horizontal + ns.Vertical = QtCore.Qt.Vertical + ns.TopToolBarArea = QtCore.Qt.TopToolBarArea + ns.StyledPanel = QtWidgets.QFrame.StyledPanel + ns.HLine = QtWidgets.QFrame.HLine + ns.VLine = QtWidgets.QFrame.VLine + ns.Raised = QtWidgets.QFrame.Raised + ns.Sunken = QtWidgets.QFrame.Sunken + ns.InstantPopup = QtWidgets.QToolButton.InstantPopup + ns.MenuButtonPopup = QtWidgets.QToolButton.MenuButtonPopup + ns.AlignTop = QtCore.Qt.AlignTop + ns.AlignLeft = QtCore.Qt.AlignLeft + ns.AlignHCenter = QtCore.Qt.AlignHCenter + ns.ItemIsUserCheckable = QtCore.Qt.ItemIsUserCheckable + ns.ItemIsUserTristate = QtCore.Qt.ItemIsUserTristate + ns.Checked = QtCore.Qt.Checked + ns.Unchecked = QtCore.Qt.Unchecked + ns.PartiallyChecked = QtCore.Qt.PartiallyChecked + ns.ReadOnly = QtCore.QFile.ReadOnly + ns.Text = QtCore.QFile.Text + ns.East = QtWidgets.QTabWidget.East + ns.SP_DockWidgetCloseButton = QtWidgets.QStyle.SP_DockWidgetCloseButton + ns.UpArrow = QtCore.Qt.UpArrow + ns.Triangular = QtWidgets.QTabWidget.Triangular + ns.Password = QtWidgets.QLineEdit.Password + ns.WindowMaximized = QtCore.Qt.WindowMaximized + ns.SolidLine = QtCore.Qt.SolidLine + ns.FlatCap = QtCore.Qt.FlatCap + ns.SquareCap = QtCore.Qt.SquareCap + ns.RoundCap = QtCore.Qt.RoundCap + ns.MiterJoin = QtCore.Qt.MiterJoin + ns.BevelJoin = QtCore.Qt.BevelJoin + ns.RoundJoin = QtCore.Qt.RoundJoin + ns.SvgMiterJoin = QtCore.Qt.SvgMiterJoin + ns.State_HasFocus = QtWidgets.QStyle.State_HasFocus + ns.State_Selected = QtWidgets.QStyle.State_Selected + ns.HoverEnter = QtCore.QEvent.HoverEnter + ns.HoverMove = QtCore.QEvent.HoverMove + ns.HoverLeave = QtCore.QEvent.HoverLeave + ns.PlaceholderText = QtGui.QPalette.PlaceholderText + ns.NoTicks = QtWidgets.QSlider.NoTicks + ns.TicksAbove = QtWidgets.QSlider.TicksAbove + ns.TicksBelow = QtWidgets.QSlider.TicksBelow + ns.TicksBothSides = QtWidgets.QSlider.TicksBothSides + ns.CC_Slider = QtWidgets.QStyle.CC_Slider + ns.SC_SliderHandle = QtWidgets.QStyle.SC_SliderHandle + ns.SC_SliderGroove = QtWidgets.QStyle.SC_SliderGroove + ns.SP_ArrowBack = QtWidgets.QStyle.SP_ArrowBack + ns.SP_ArrowDown = QtWidgets.QStyle.SP_ArrowDown + ns.SP_ArrowForward = QtWidgets.QStyle.SP_ArrowForward + ns.SP_ArrowLeft = QtWidgets.QStyle.SP_ArrowLeft + ns.SP_ArrowRight = QtWidgets.QStyle.SP_ArrowRight + ns.SP_ArrowUp = QtWidgets.QStyle.SP_ArrowUp + ns.SP_BrowserReload = QtWidgets.QStyle.SP_BrowserReload + ns.SP_BrowserStop = QtWidgets.QStyle.SP_BrowserStop + ns.SP_CommandLink = QtWidgets.QStyle.SP_CommandLink + ns.SP_ComputerIcon = QtWidgets.QStyle.SP_ComputerIcon + ns.SP_CustomBase = QtWidgets.QStyle.SP_CustomBase + ns.SP_DesktopIcon = QtWidgets.QStyle.SP_DesktopIcon + ns.SP_DialogApplyButton = QtWidgets.QStyle.SP_DialogApplyButton + ns.SP_DialogCancelButton = QtWidgets.QStyle.SP_DialogCancelButton + ns.SP_DialogCloseButton = QtWidgets.QStyle.SP_DialogCloseButton + ns.SP_DialogDiscardButton = QtWidgets.QStyle.SP_DialogDiscardButton + ns.SP_DialogHelpButton = QtWidgets.QStyle.SP_DialogHelpButton + ns.SP_DialogNoButton = QtWidgets.QStyle.SP_DialogNoButton + ns.SP_DialogOkButton = QtWidgets.QStyle.SP_DialogOkButton + ns.SP_DialogOpenButton = QtWidgets.QStyle.SP_DialogOpenButton + ns.SP_DialogResetButton = QtWidgets.QStyle.SP_DialogResetButton + ns.SP_DialogSaveButton = QtWidgets.QStyle.SP_DialogSaveButton + ns.SP_DialogYesButton = QtWidgets.QStyle.SP_DialogYesButton + ns.SP_DirClosedIcon = QtWidgets.QStyle.SP_DirClosedIcon + ns.SP_DirHomeIcon = QtWidgets.QStyle.SP_DirHomeIcon + ns.SP_DirIcon = QtWidgets.QStyle.SP_DirIcon + ns.SP_DirLinkIcon = QtWidgets.QStyle.SP_DirLinkIcon + ns.SP_DirLinkOpenIcon = QtWidgets.QStyle.SP_DirLinkOpenIcon + ns.SP_DirOpenIcon = QtWidgets.QStyle.SP_DirOpenIcon + ns.SP_DockWidgetCloseButton = QtWidgets.QStyle.SP_DockWidgetCloseButton + ns.SP_DriveCDIcon = QtWidgets.QStyle.SP_DriveCDIcon + ns.SP_DriveDVDIcon = QtWidgets.QStyle.SP_DriveDVDIcon + ns.SP_DriveFDIcon = QtWidgets.QStyle.SP_DriveFDIcon + ns.SP_DriveHDIcon = QtWidgets.QStyle.SP_DriveHDIcon + ns.SP_DriveNetIcon = QtWidgets.QStyle.SP_DriveNetIcon + ns.SP_FileDialogBack = QtWidgets.QStyle.SP_FileDialogBack + ns.SP_FileDialogContentsView = QtWidgets.QStyle.SP_FileDialogContentsView + ns.SP_FileDialogDetailedView = QtWidgets.QStyle.SP_FileDialogDetailedView + ns.SP_FileDialogEnd = QtWidgets.QStyle.SP_FileDialogEnd + ns.SP_FileDialogInfoView = QtWidgets.QStyle.SP_FileDialogInfoView + ns.SP_FileDialogListView = QtWidgets.QStyle.SP_FileDialogListView + ns.SP_FileDialogNewFolder = QtWidgets.QStyle.SP_FileDialogNewFolder + ns.SP_FileDialogStart = QtWidgets.QStyle.SP_FileDialogStart + ns.SP_FileDialogToParent = QtWidgets.QStyle.SP_FileDialogToParent + ns.SP_FileIcon = QtWidgets.QStyle.SP_FileIcon + ns.SP_FileLinkIcon = QtWidgets.QStyle.SP_FileLinkIcon + ns.SP_MediaPause = QtWidgets.QStyle.SP_MediaPause + ns.SP_MediaPlay = QtWidgets.QStyle.SP_MediaPlay + ns.SP_MediaSeekBackward = QtWidgets.QStyle.SP_MediaSeekBackward + ns.SP_MediaSeekForward = QtWidgets.QStyle.SP_MediaSeekForward + ns.SP_MediaSkipBackward = QtWidgets.QStyle.SP_MediaSkipBackward + ns.SP_MediaSkipForward = QtWidgets.QStyle.SP_MediaSkipForward + ns.SP_MediaStop = QtWidgets.QStyle.SP_MediaStop + ns.SP_MediaVolume = QtWidgets.QStyle.SP_MediaVolume + ns.SP_MediaVolumeMuted = QtWidgets.QStyle.SP_MediaVolumeMuted + ns.SP_LineEditClearButton = QtWidgets.QStyle.SP_LineEditClearButton + ns.SP_DialogYesToAllButton = QtWidgets.QStyle.SP_DialogYesToAllButton + ns.SP_DialogNoToAllButton = QtWidgets.QStyle.SP_DialogNoToAllButton + ns.SP_DialogSaveAllButton = QtWidgets.QStyle.SP_DialogSaveAllButton + ns.SP_DialogAbortButton = QtWidgets.QStyle.SP_DialogAbortButton + ns.SP_DialogRetryButton = QtWidgets.QStyle.SP_DialogRetryButton + ns.SP_DialogIgnoreButton = QtWidgets.QStyle.SP_DialogIgnoreButton + ns.SP_RestoreDefaultsButton = QtWidgets.QStyle.SP_RestoreDefaultsButton + ns.SP_MessageBoxCritical = QtWidgets.QStyle.SP_MessageBoxCritical + ns.SP_MessageBoxInformation = QtWidgets.QStyle.SP_MessageBoxInformation + ns.SP_MessageBoxQuestion = QtWidgets.QStyle.SP_MessageBoxQuestion + ns.SP_MessageBoxWarning = QtWidgets.QStyle.SP_MessageBoxWarning + ns.SP_TitleBarCloseButton = QtWidgets.QStyle.SP_TitleBarCloseButton + ns.SP_TitleBarContextHelpButton = QtWidgets.QStyle.SP_TitleBarContextHelpButton + ns.SP_TitleBarMaxButton = QtWidgets.QStyle.SP_TitleBarMaxButton + ns.SP_TitleBarMenuButton = QtWidgets.QStyle.SP_TitleBarMenuButton + ns.SP_TitleBarMinButton = QtWidgets.QStyle.SP_TitleBarMinButton + ns.SP_TitleBarNormalButton = QtWidgets.QStyle.SP_TitleBarNormalButton + ns.SP_TitleBarShadeButton = QtWidgets.QStyle.SP_TitleBarShadeButton + ns.SP_TitleBarUnshadeButton = QtWidgets.QStyle.SP_TitleBarUnshadeButton + ns.SP_ToolBarHorizontalExtensionButton = QtWidgets.QStyle.SP_ToolBarHorizontalExtensionButton + ns.SP_ToolBarVerticalExtensionButton = QtWidgets.QStyle.SP_ToolBarVerticalExtensionButton + ns.SP_TrashIcon = QtWidgets.QStyle.SP_TrashIcon + ns.SP_VistaShield = QtWidgets.QStyle.SP_VistaShield + + return ns + +def get_colors(args, compat): + '''Create shared colors dependent on the stylesheet.''' + + ns = argparse.Namespace() + ns.Selected = compat.QtGui.QColor(61, 174, 233) + ns.PlaceholderColor = compat.QtGui.QColor(255, 0, 0) + ns.TickColor = compat.QtGui.QColor(255, 0, 0) + if 'dark' in args.stylesheet: + ns.GrooveBackground = compat.QtGui.QColor(98, 101, 104) + ns.GrooveBorder = compat.QtGui.QColor(49, 54, 59) + ns.HandleBackground = compat.QtGui.QColor(29, 32, 35) + ns.HandleBorder = compat.QtGui.QColor(98, 101, 104) + ns.Notch = compat.QtGui.QColor(51, 78, 94) + ns.PlaceholderColor = compat.QtGui.QColor(118, 121, 124) + ns.TickColor = compat.QtGui.QColor(51, 78, 94) + elif 'light' in args.stylesheet: + ns.GrooveBackground = compat.QtGui.QColor(106, 105, 105, 179) + ns.GrooveBorder = compat.QtGui.QColor(239, 240, 241) + ns.HandleBackground = compat.QtGui.QColor(239, 240, 241) + ns.HandleBorder = compat.QtGui.QColor(106, 105, 105, 179) + ns.Notch = compat.QtGui.QColor(61, 173, 232, 51) + ns.PlaceholderColor = compat.QtGui.QColor(186, 185, 184) + ns.TickColor = compat.QtGui.QColor(61, 173, 232, 51) + + return ns + +def get_icon_map(args, compat): + '''Create a map of standard icons to resource paths.''' + + icon_map = { + compat.SP_TitleBarMinButton: 'minimize.svg', + compat.SP_TitleBarMenuButton: 'menu.svg', + compat.SP_TitleBarMaxButton: 'maximize.svg', + compat.SP_TitleBarCloseButton: 'window_close.svg', + compat.SP_TitleBarNormalButton: 'restore.svg', + compat.SP_TitleBarShadeButton: 'shade.svg', + compat.SP_TitleBarUnshadeButton: 'unshade.svg', + compat.SP_TitleBarContextHelpButton: 'help.svg', + compat.SP_MessageBoxInformation: 'message_information.svg', + compat.SP_MessageBoxWarning: 'message_warning.svg', + compat.SP_MessageBoxCritical: 'message_critical.svg', + compat.SP_MessageBoxQuestion: 'message_question.svg', + compat.SP_DesktopIcon: 'desktop.svg', + compat.SP_TrashIcon: 'trash.svg', + compat.SP_ComputerIcon: 'computer.svg', + compat.SP_DriveFDIcon: 'floppy_drive.svg', + compat.SP_DriveHDIcon: 'hard_drive.svg', + compat.SP_DriveCDIcon: 'disc_drive.svg', + compat.SP_DriveDVDIcon: 'disc_drive.svg', + compat.SP_DriveNetIcon: 'network_drive.svg', + compat.SP_DirHomeIcon: 'home_directory.svg', + compat.SP_DirOpenIcon: 'folder_open.svg', + compat.SP_DirClosedIcon: 'folder.svg', + compat.SP_DirIcon: 'folder.svg', + compat.SP_DirLinkIcon: 'folder_link.svg', + compat.SP_DirLinkOpenIcon: 'folder_open_link.svg', + compat.SP_FileIcon: 'file.svg', + compat.SP_FileLinkIcon: 'file_link.svg', + compat.SP_FileDialogStart: 'file_dialog_start.svg', + compat.SP_FileDialogEnd: 'file_dialog_end.svg', + compat.SP_FileDialogToParent: 'up_arrow.svg', + compat.SP_FileDialogNewFolder: 'folder.svg', + compat.SP_FileDialogDetailedView: 'file_dialog_detailed.svg', + compat.SP_FileDialogInfoView: 'file_dialog_info.svg', + compat.SP_FileDialogContentsView: 'file_dialog_contents.svg', + compat.SP_FileDialogListView: 'file_dialog_list.svg', + compat.SP_FileDialogBack: 'left_arrow.svg', + compat.SP_DockWidgetCloseButton: 'close.svg', + compat.SP_ToolBarHorizontalExtensionButton: 'horizontal_extension.svg', + compat.SP_ToolBarVerticalExtensionButton: 'vertical_extension.svg', + compat.SP_DialogOkButton: 'dialog_ok.svg', + compat.SP_DialogCancelButton: 'dialog_cancel.svg', + compat.SP_DialogHelpButton: 'dialog_help.svg', + compat.SP_DialogOpenButton: 'dialog_open.svg', + compat.SP_DialogSaveButton: 'dialog_save.svg', + compat.SP_DialogCloseButton: 'dialog_close.svg', + compat.SP_DialogApplyButton: 'dialog_apply.svg', + compat.SP_DialogResetButton: 'dialog_reset.svg', + compat.SP_DialogDiscardButton: 'dialog_discard.svg', + compat.SP_DialogYesButton: 'dialog_apply.svg', + compat.SP_DialogNoButton: 'dialog_no.svg', + compat.SP_ArrowUp: 'up_arrow.svg', + compat.SP_ArrowDown: 'down_arrow.svg', + compat.SP_ArrowLeft: 'left_arrow.svg', + compat.SP_ArrowRight: 'right_arrow.svg', + compat.SP_ArrowBack: 'left_arrow.svg', + compat.SP_ArrowForward: 'right_arrow.svg', + compat.SP_CommandLink: 'right_arrow.svg', + compat.SP_VistaShield: 'vista_shield.svg', + compat.SP_BrowserReload: 'browser_refresh.svg', + compat.SP_BrowserStop: 'browser_refresh_stop.svg', + compat.SP_MediaPlay: 'play.svg', + compat.SP_MediaStop: 'stop.svg', + compat.SP_MediaPause: 'pause.svg', + compat.SP_MediaSkipForward: 'skip_backward.svg', + compat.SP_MediaSkipBackward: 'skip_forward.svg', + compat.SP_MediaSeekForward: 'seek_forward.svg', + compat.SP_MediaSeekBackward: 'seek_backward.svg', + compat.SP_MediaVolume: 'volume.svg', + compat.SP_MediaVolumeMuted: 'volume_muted.svg', + compat.SP_LineEditClearButton: 'clear_text.svg', + compat.SP_DialogYesToAllButton: 'dialog_yes_to_all.svg', + compat.SP_DialogNoToAllButton: 'dialog_no.svg', + compat.SP_DialogSaveAllButton: 'dialog_save_all.svg', + compat.SP_DialogAbortButton: 'dialog_cancel.svg', + compat.SP_DialogRetryButton: 'dialog_retry.svg', + compat.SP_DialogIgnoreButton: 'dialog_ignore.svg', + compat.SP_RestoreDefaultsButton: 'restore_defaults.svg', + } + if compat.QtCore.QT_VERSION >= 393984: + icon_map[compat.SP_TabCloseButton] = 'tab_close.svg' + + return icon_map + +def setup_app(args, unknown, compat, style_class=None): + '''Setup code for the Qt application.''' + + if args.scale != 1: + os.environ['QT_SCALE_FACTOR'] = str(args.scale) + else: + os.environ['QT_AUTO_SCREEN_SCALE_FACTOR'] = '1' + + app = compat.QtWidgets.QApplication(sys.argv[:1] + unknown) + if args.style != 'native': + style = compat.QtWidgets.QStyleFactory.create(args.style) + if style_class is not None: + style = style_class(style) + app.setStyle(style) + + window = compat.QtWidgets.QMainWindow() + + # use the default font size + font = app.font() + if args.font_size > 0: + font.setPointSizeF(args.font_size) + if args.font_family: + font.setFamily(args.font_family) + app.setFont(font) + + return app, window + +def exec_app(args, app, window, compat): + '''Show and execute the Qt application.''' + + # setup stylesheet + if args.stylesheet != 'native': + resource_format = get_resources(args) + stylesheet = get_stylesheet(resource_format) + file = compat.QtCore.QFile(stylesheet) + file.open(compat.ReadOnly | compat.Text) + stream = compat.QtCore.QTextStream(file) + app.setStyleSheet(stream.readAll()) + + window.show() + return execute(args, app) + +def execute(args, widget): + '''Shared code to call `exec()` on a widget.''' + + if args.pyqt6: + return widget.exec() + return widget.exec_() + +def native_icon(style, icon, option=None, widget=None): + '''Get a standard icon for the native style''' + return style.standardIcon(icon, option, widget) + +def stylesheet_icon(args, style, icon, icon_map, option=None, widget=None): + '''Get a standard icon for the stylesheet style''' + + if args.pyqt6: + from PyQt6 import QtCore, QtGui, QtWidgets + else: + from PyQt5 import QtCore, QtGui, QtWidgets + + path = icon_map[icon] + resource_format = get_resources(args) + resource = f'{resource_format}{path}' + if QtCore.QFile.exists(resource): + return QtGui.QIcon(resource) + return QtWidgets.QCommonStyle.standardIcon(style, icon, option, widget) + +def style_icon(args, style, icon, icon_map, option=None, widget=None): + '''Get the stylized icon, either native or in the stylesheet.''' + + if args.stylesheet == 'native': + return native_icon(style, icon, option, widget) + return stylesheet_icon(args, style, icon, icon_map, option, widget) diff --git a/example/slider.py b/example/slider.py index 5d75d2a..79c737a 100644 --- a/example/slider.py +++ b/example/slider.py @@ -31,99 +31,14 @@ get customized styling behavior with a QSlider. ''' -import argparse -import os +import shared import sys -example_dir = os.path.dirname(os.path.realpath(__file__)) -home = os.path.dirname(example_dir) -dist = os.path.join(home, 'dist') - -# Create our arguments. -parser = argparse.ArgumentParser(description='Configurations for the Qt5 application.') -parser.add_argument( - '--stylesheet', - help='''stylesheet name''', - default='native' -) -# Know working styles include: -# 1. Fusion -# 2. Windows -parser.add_argument( - '--style', - help='''application style, which is different than the stylesheet''', - default='native' -) -parser.add_argument( - '--font-size', - help='''font size for the application''', - type=float, - default=-1 -) -parser.add_argument( - '--font-family', - help='''the font family''' -) -parser.add_argument( - '--scale', - help='''scale factor for the UI''', - type=float, - default=1, -) -parser.add_argument( - '--pyqt6', - help='''use PyQt6 rather than PyQt5.''', - action='store_true' -) -parser.add_argument( - '--use-x11', - help='''force the use of x11 on compatible systems.''', - action='store_true' -) - -args, unknown = parser.parse_known_args() -if args.pyqt6: - from PyQt6 import QtCore, QtGui, QtWidgets - QtCore.QDir.addSearchPath(args.stylesheet, f'{dist}/pyqt6/{args.stylesheet}/') - resource_format = f'{args.stylesheet}:' -else: - sys.path.insert(0, home) - from PyQt5 import QtCore, QtGui, QtWidgets - import breeze_resources - resource_format = f':/{args.stylesheet}/' -stylesheet = f'{resource_format}stylesheet.qss' - -# Compat definitions, between Qt5 and Qt6. -if args.pyqt6: - AlignHCenter = QtCore.Qt.AlignmentFlag.AlignHCenter - ReadOnly = QtCore.QFile.OpenModeFlag.ReadOnly - Text = QtCore.QFile.OpenModeFlag.Text - Horizontal = QtCore.Qt.Orientation.Horizontal - NoTicks = QtWidgets.QSlider.TickPosition.NoTicks - TicksAbove = QtWidgets.QSlider.TickPosition.TicksAbove - TicksBelow = QtWidgets.QSlider.TickPosition.TicksBelow - TicksBothSides = QtWidgets.QSlider.TickPosition.TicksBothSides - CC_Slider = QtWidgets.QStyle.ComplexControl.CC_Slider - SC_SliderHandle = QtWidgets.QStyle.SubControl.SC_SliderHandle - SC_SliderGroove = QtWidgets.QStyle.SubControl.SC_SliderGroove -else: - AlignHCenter = QtCore.Qt.AlignHCenter - ReadOnly = QtCore.QFile.ReadOnly - Text = QtCore.QFile.Text - Horizontal = QtCore.Qt.Horizontal - NoTicks = QtWidgets.QSlider.NoTicks - TicksAbove = QtWidgets.QSlider.TicksAbove - TicksBelow = QtWidgets.QSlider.TicksBelow - TicksBothSides = QtWidgets.QSlider.TicksBothSides - CC_Slider = QtWidgets.QStyle.CC_Slider - SC_SliderHandle = QtWidgets.QStyle.SC_SliderHandle - SC_SliderGroove = QtWidgets.QStyle.SC_SliderGroove - -TICK_COLOR = QtGui.QColor(255, 0, 0) -if 'dark' in args.stylesheet: - TICK_COLOR = QtGui.QColor(51, 78, 94) -elif 'light' in args.stylesheet: - TICK_COLOR = QtGui.QColor(61, 173, 232, 51) +parser = shared.create_parser() +args, unknown = shared.parse_args(parser) +QtCore, QtGui, QtWidgets = shared.import_qt(args) +compat = shared.get_compat_definitions(args) +colors = shared.get_colors(args, compat) class Slider(QtWidgets.QSlider): @@ -140,31 +55,36 @@ class Slider(QtWidgets.QSlider): self.initStyleOption(options) style = self.style() - handle = style.subControlRect(CC_Slider, options, SC_SliderHandle, self) + handle = style.subControlRect( + compat.CC_Slider, + options, + compat.SC_SliderHandle, + self, + ) interval = self.tickInterval() or self.pageStep() position = self.tickPosition() - if position != NoTicks and interval != 0: + if position != compat.NoTicks and interval != 0: minimum = self.minimum() maximum = self.maximum() - painter.setPen(TICK_COLOR) + painter.setPen(colors.TickColor) for i in range(minimum, maximum + interval, interval): percent = (i - minimum) / (maximum - minimum + 1) + 0.005 width = (self.width() - handle.width()) + handle.width() / 2 x = int(percent * width) h = 4 - if position == TicksBothSides or position == TicksAbove: + if position == compat.TicksBothSides or position == compat.TicksAbove: y = self.rect().top() painter.drawLine(x, y, x, y + h) - if position == TicksBothSides or position == TicksBelow: + if position == compat.TicksBothSides or position == compat.TicksBelow: y = self.rect().bottom() painter.drawLine(x, y, x, y - h) - options.subControls = SC_SliderGroove - painter.drawComplexControl(CC_Slider, options) + options.subControls = compat.SC_SliderGroove + painter.drawComplexControl(compat.CC_Slider, options) - options.subControls = SC_SliderHandle - painter.drawComplexControl(CC_Slider, options) + options.subControls = compat.SC_SliderHandle + painter.drawComplexControl(compat.CC_Slider, options) class Ui: @@ -177,13 +97,13 @@ class Ui: self.centralwidget.setObjectName('centralwidget') self.layout = QtWidgets.QVBoxLayout(self.centralwidget) self.layout.setObjectName('layout') - self.layout.setAlignment(AlignHCenter) + self.layout.setAlignment(compat.AlignHCenter) MainWindow.setCentralWidget(self.centralwidget) self.slider = Slider(self.centralwidget) - self.slider.setOrientation(Horizontal) + self.slider.setOrientation(compat.Horizontal) self.slider.setTickInterval(5) - self.slider.setTickPosition(TicksAbove) + self.slider.setTickPosition(compat.TicksAbove) self.slider.setObjectName('slider') self.layout.addWidget(self.slider) @@ -191,44 +111,14 @@ class Ui: def main(): 'Application entry point' - if args.scale != 1: - os.environ['QT_SCALE_FACTOR'] = str(args.scale) - else: - os.environ['QT_AUTO_SCREEN_SCALE_FACTOR'] = '1' - - app = QtWidgets.QApplication(sys.argv[:1] + unknown) - if args.style != 'native': - style = QtWidgets.QStyleFactory.create(args.style) - app.setStyle(style) - - window = QtWidgets.QMainWindow() + app, window = shared.setup_app(args, unknown, compat) # setup ui ui = Ui() ui.setup(window) window.setWindowTitle('QSlider with Ticks.') - # use the default font size - font = app.font() - if args.font_size > 0: - font.setPointSizeF(args.font_size) - if args.font_family: - font.setFamily(args.font_family) - app.setFont(font) - - # setup stylesheet - if args.stylesheet != 'native': - file = QtCore.QFile(stylesheet) - file.open(ReadOnly | Text) - stream = QtCore.QTextStream(file) - app.setStyleSheet(stream.readAll()) - - # run - window.show() - if args.pyqt6: - return app.exec() - else: - return app.exec_() + return shared.exec_app(args, app, window, compat) if __name__ == '__main__': sys.exit(main()) diff --git a/example/standard_icons.py b/example/standard_icons.py index 91bf323..5608ba1 100644 --- a/example/standard_icons.py +++ b/example/standard_icons.py @@ -2,8 +2,7 @@ # # The MIT License (MIT) # -# Copyright (c) <2013-2014> -# Modified by Alex Huszagh +# Copyright (c) <2022-Present> # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the 'Software'), to deal @@ -30,361 +29,18 @@ Example overriding QCommonStyle for custom standard icons. ''' -import argparse -import os +import shared import sys -example_dir = os.path.dirname(os.path.realpath(__file__)) -home = os.path.dirname(example_dir) -dist = os.path.join(home, 'dist') +parser = shared.create_parser() +args, unknown = shared.parse_args(parser) +QtCore, QtGui, QtWidgets = shared.import_qt(args) +compat = shared.get_compat_definitions(args) +ICON_MAP = shared.get_icon_map(args, compat) -# Create our arguments. -parser = argparse.ArgumentParser(description='Configurations for the Qt5 application.') -# Know working styles include: -# 1. Fusion -# 2. Windows -parser.add_argument( - '--style', - help='''application style, which is different than the stylesheet''', - default='fusion' -) -parser.add_argument( - '--stylesheet', - help='''stylesheet name''', - default='native' -) -parser.add_argument( - '--font-size', - help='''font size for the application''', - type=float, - default=-1 -) -parser.add_argument( - '--font-family', - help='''the font family''' -) -parser.add_argument( - '--scale', - help='''scale factor for the UI''', - type=float, - default=1, -) -parser.add_argument( - '--pyqt6', - help='''use PyQt6 rather than PyQt5.''', - action='store_true' -) -parser.add_argument( - '--use-x11', - help='''force the use of x11 on compatible systems.''', - action='store_true' -) - -args, unknown = parser.parse_known_args() -if args.pyqt6: - from PyQt6 import QtCore, QtGui, QtWidgets - QtCore.QDir.addSearchPath(args.stylesheet, f'{dist}/pyqt6/{args.stylesheet}/') - resource_format = f'{args.stylesheet}:' -else: - sys.path.insert(0, home) - from PyQt5 import QtCore, QtGui, QtWidgets - import breeze_resources - resource_format = f':/{args.stylesheet}/' -stylesheet = f'{resource_format}stylesheet.qss' - -# Compat definitions, between Qt5 and Qt6. -if args.pyqt6: - QAction = QtGui.QAction - Horizontal = QtCore.Qt.Orientation.Horizontal - AlignHCenter = QtCore.Qt.AlignmentFlag.AlignHCenter - HLine = QtWidgets.QFrame.Shape.HLine - Sunken = QtWidgets.QFrame.Shadow.Sunken - ReadOnly = QtCore.QFile.OpenModeFlag.ReadOnly - Text = QtCore.QFile.OpenModeFlag.Text - SP_ArrowBack = QtWidgets.QStyle.StandardPixmap.SP_ArrowBack - SP_ArrowDown = QtWidgets.QStyle.StandardPixmap.SP_ArrowDown - SP_ArrowForward = QtWidgets.QStyle.StandardPixmap.SP_ArrowForward - SP_ArrowLeft = QtWidgets.QStyle.StandardPixmap.SP_ArrowLeft - SP_ArrowRight = QtWidgets.QStyle.StandardPixmap.SP_ArrowRight - SP_ArrowUp = QtWidgets.QStyle.StandardPixmap.SP_ArrowUp - SP_BrowserReload = QtWidgets.QStyle.StandardPixmap.SP_BrowserReload - SP_BrowserStop = QtWidgets.QStyle.StandardPixmap.SP_BrowserStop - SP_CommandLink = QtWidgets.QStyle.StandardPixmap.SP_CommandLink - SP_ComputerIcon = QtWidgets.QStyle.StandardPixmap.SP_ComputerIcon - SP_CustomBase = QtWidgets.QStyle.StandardPixmap.SP_CustomBase - SP_DesktopIcon = QtWidgets.QStyle.StandardPixmap.SP_DesktopIcon - SP_DialogApplyButton = QtWidgets.QStyle.StandardPixmap.SP_DialogApplyButton - SP_DialogCancelButton = QtWidgets.QStyle.StandardPixmap.SP_DialogCancelButton - SP_DialogCloseButton = QtWidgets.QStyle.StandardPixmap.SP_DialogCloseButton - SP_DialogDiscardButton = QtWidgets.QStyle.StandardPixmap.SP_DialogDiscardButton - SP_DialogHelpButton = QtWidgets.QStyle.StandardPixmap.SP_DialogHelpButton - SP_DialogNoButton = QtWidgets.QStyle.StandardPixmap.SP_DialogNoButton - SP_DialogOkButton = QtWidgets.QStyle.StandardPixmap.SP_DialogOkButton - SP_DialogOpenButton = QtWidgets.QStyle.StandardPixmap.SP_DialogOpenButton - SP_DialogResetButton = QtWidgets.QStyle.StandardPixmap.SP_DialogResetButton - SP_DialogSaveButton = QtWidgets.QStyle.StandardPixmap.SP_DialogSaveButton - SP_DialogYesButton = QtWidgets.QStyle.StandardPixmap.SP_DialogYesButton - SP_DirClosedIcon = QtWidgets.QStyle.StandardPixmap.SP_DirClosedIcon - SP_DirHomeIcon = QtWidgets.QStyle.StandardPixmap.SP_DirHomeIcon - SP_DirIcon = QtWidgets.QStyle.StandardPixmap.SP_DirIcon - SP_DirLinkIcon = QtWidgets.QStyle.StandardPixmap.SP_DirLinkIcon - SP_DirLinkOpenIcon = QtWidgets.QStyle.StandardPixmap.SP_DirLinkOpenIcon - SP_DirOpenIcon = QtWidgets.QStyle.StandardPixmap.SP_DirOpenIcon - SP_DockWidgetCloseButton = QtWidgets.QStyle.StandardPixmap.SP_DockWidgetCloseButton - SP_DriveCDIcon = QtWidgets.QStyle.StandardPixmap.SP_DriveCDIcon - SP_DriveDVDIcon = QtWidgets.QStyle.StandardPixmap.SP_DriveDVDIcon - SP_DriveFDIcon = QtWidgets.QStyle.StandardPixmap.SP_DriveFDIcon - SP_DriveHDIcon = QtWidgets.QStyle.StandardPixmap.SP_DriveHDIcon - SP_DriveNetIcon = QtWidgets.QStyle.StandardPixmap.SP_DriveNetIcon - SP_FileDialogBack = QtWidgets.QStyle.StandardPixmap.SP_FileDialogBack - SP_FileDialogContentsView = QtWidgets.QStyle.StandardPixmap.SP_FileDialogContentsView - SP_FileDialogDetailedView = QtWidgets.QStyle.StandardPixmap.SP_FileDialogDetailedView - SP_FileDialogEnd = QtWidgets.QStyle.StandardPixmap.SP_FileDialogEnd - SP_FileDialogInfoView = QtWidgets.QStyle.StandardPixmap.SP_FileDialogInfoView - SP_FileDialogListView = QtWidgets.QStyle.StandardPixmap.SP_FileDialogListView - SP_FileDialogNewFolder = QtWidgets.QStyle.StandardPixmap.SP_FileDialogNewFolder - SP_FileDialogStart = QtWidgets.QStyle.StandardPixmap.SP_FileDialogStart - SP_FileDialogToParent = QtWidgets.QStyle.StandardPixmap.SP_FileDialogToParent - SP_FileIcon = QtWidgets.QStyle.StandardPixmap.SP_FileIcon - SP_FileLinkIcon = QtWidgets.QStyle.StandardPixmap.SP_FileLinkIcon - SP_MediaPause = QtWidgets.QStyle.StandardPixmap.SP_MediaPause - SP_MediaPlay = QtWidgets.QStyle.StandardPixmap.SP_MediaPlay - SP_MediaSeekBackward = QtWidgets.QStyle.StandardPixmap.SP_MediaSeekBackward - SP_MediaSeekForward = QtWidgets.QStyle.StandardPixmap.SP_MediaSeekForward - SP_MediaSkipBackward = QtWidgets.QStyle.StandardPixmap.SP_MediaSkipBackward - SP_MediaSkipForward = QtWidgets.QStyle.StandardPixmap.SP_MediaSkipForward - SP_MediaStop = QtWidgets.QStyle.StandardPixmap.SP_MediaStop - SP_MediaVolume = QtWidgets.QStyle.StandardPixmap.SP_MediaVolume - SP_MediaVolumeMuted = QtWidgets.QStyle.StandardPixmap.SP_MediaVolumeMuted - SP_LineEditClearButton = QtWidgets.QStyle.StandardPixmap.SP_LineEditClearButton - SP_DialogYesToAllButton = QtWidgets.QStyle.StandardPixmap.SP_DialogYesToAllButton - SP_DialogNoToAllButton = QtWidgets.QStyle.StandardPixmap.SP_DialogNoToAllButton - SP_DialogSaveAllButton = QtWidgets.QStyle.StandardPixmap.SP_DialogSaveAllButton - SP_DialogAbortButton = QtWidgets.QStyle.StandardPixmap.SP_DialogAbortButton - SP_DialogRetryButton = QtWidgets.QStyle.StandardPixmap.SP_DialogRetryButton - SP_DialogIgnoreButton = QtWidgets.QStyle.StandardPixmap.SP_DialogIgnoreButton - SP_RestoreDefaultsButton = QtWidgets.QStyle.StandardPixmap.SP_RestoreDefaultsButton - if QtCore.QT_VERSION >= 393984: - SP_TabCloseButton = QtWidgets.QStyle.StandardPixmap.SP_TabCloseButton - SP_MessageBoxCritical = QtWidgets.QStyle.StandardPixmap.SP_MessageBoxCritical - SP_MessageBoxInformation = QtWidgets.QStyle.StandardPixmap.SP_MessageBoxInformation - SP_MessageBoxQuestion = QtWidgets.QStyle.StandardPixmap.SP_MessageBoxQuestion - SP_MessageBoxWarning = QtWidgets.QStyle.StandardPixmap.SP_MessageBoxWarning - SP_TitleBarCloseButton = QtWidgets.QStyle.StandardPixmap.SP_TitleBarCloseButton - SP_TitleBarContextHelpButton = QtWidgets.QStyle.StandardPixmap.SP_TitleBarContextHelpButton - SP_TitleBarMaxButton = QtWidgets.QStyle.StandardPixmap.SP_TitleBarMaxButton - SP_TitleBarMenuButton = QtWidgets.QStyle.StandardPixmap.SP_TitleBarMenuButton - SP_TitleBarMinButton = QtWidgets.QStyle.StandardPixmap.SP_TitleBarMinButton - SP_TitleBarNormalButton = QtWidgets.QStyle.StandardPixmap.SP_TitleBarNormalButton - SP_TitleBarShadeButton = QtWidgets.QStyle.StandardPixmap.SP_TitleBarShadeButton - SP_TitleBarUnshadeButton = QtWidgets.QStyle.StandardPixmap.SP_TitleBarUnshadeButton - SP_ToolBarHorizontalExtensionButton = QtWidgets.QStyle.StandardPixmap.SP_ToolBarHorizontalExtensionButton - SP_ToolBarVerticalExtensionButton = QtWidgets.QStyle.StandardPixmap.SP_ToolBarVerticalExtensionButton - SP_TrashIcon = QtWidgets.QStyle.StandardPixmap.SP_TrashIcon - SP_VistaShield = QtWidgets.QStyle.StandardPixmap.SP_VistaShield -else: - QAction = QtWidgets.QAction - Horizontal = QtCore.Qt.Horizontal - AlignHCenter = QtCore.Qt.AlignHCenter - HLine = QtWidgets.QFrame.HLine - Sunken = QtWidgets.QFrame.Sunken - ReadOnly = QtCore.QFile.ReadOnly - Text = QtCore.QFile.Text - SP_ArrowBack = QtWidgets.QStyle.SP_ArrowBack - SP_ArrowDown = QtWidgets.QStyle.SP_ArrowDown - SP_ArrowForward = QtWidgets.QStyle.SP_ArrowForward - SP_ArrowLeft = QtWidgets.QStyle.SP_ArrowLeft - SP_ArrowRight = QtWidgets.QStyle.SP_ArrowRight - SP_ArrowUp = QtWidgets.QStyle.SP_ArrowUp - SP_BrowserReload = QtWidgets.QStyle.SP_BrowserReload - SP_BrowserStop = QtWidgets.QStyle.SP_BrowserStop - SP_CommandLink = QtWidgets.QStyle.SP_CommandLink - SP_ComputerIcon = QtWidgets.QStyle.SP_ComputerIcon - SP_CustomBase = QtWidgets.QStyle.SP_CustomBase - SP_DesktopIcon = QtWidgets.QStyle.SP_DesktopIcon - SP_DialogApplyButton = QtWidgets.QStyle.SP_DialogApplyButton - SP_DialogCancelButton = QtWidgets.QStyle.SP_DialogCancelButton - SP_DialogCloseButton = QtWidgets.QStyle.SP_DialogCloseButton - SP_DialogDiscardButton = QtWidgets.QStyle.SP_DialogDiscardButton - SP_DialogHelpButton = QtWidgets.QStyle.SP_DialogHelpButton - SP_DialogNoButton = QtWidgets.QStyle.SP_DialogNoButton - SP_DialogOkButton = QtWidgets.QStyle.SP_DialogOkButton - SP_DialogOpenButton = QtWidgets.QStyle.SP_DialogOpenButton - SP_DialogResetButton = QtWidgets.QStyle.SP_DialogResetButton - SP_DialogSaveButton = QtWidgets.QStyle.SP_DialogSaveButton - SP_DialogYesButton = QtWidgets.QStyle.SP_DialogYesButton - SP_DirClosedIcon = QtWidgets.QStyle.SP_DirClosedIcon - SP_DirHomeIcon = QtWidgets.QStyle.SP_DirHomeIcon - SP_DirIcon = QtWidgets.QStyle.SP_DirIcon - SP_DirLinkIcon = QtWidgets.QStyle.SP_DirLinkIcon - SP_DirLinkOpenIcon = QtWidgets.QStyle.SP_DirLinkOpenIcon - SP_DirOpenIcon = QtWidgets.QStyle.SP_DirOpenIcon - SP_DockWidgetCloseButton = QtWidgets.QStyle.SP_DockWidgetCloseButton - SP_DriveCDIcon = QtWidgets.QStyle.SP_DriveCDIcon - SP_DriveDVDIcon = QtWidgets.QStyle.SP_DriveDVDIcon - SP_DriveFDIcon = QtWidgets.QStyle.SP_DriveFDIcon - SP_DriveHDIcon = QtWidgets.QStyle.SP_DriveHDIcon - SP_DriveNetIcon = QtWidgets.QStyle.SP_DriveNetIcon - SP_FileDialogBack = QtWidgets.QStyle.SP_FileDialogBack - SP_FileDialogContentsView = QtWidgets.QStyle.SP_FileDialogContentsView - SP_FileDialogDetailedView = QtWidgets.QStyle.SP_FileDialogDetailedView - SP_FileDialogEnd = QtWidgets.QStyle.SP_FileDialogEnd - SP_FileDialogInfoView = QtWidgets.QStyle.SP_FileDialogInfoView - SP_FileDialogListView = QtWidgets.QStyle.SP_FileDialogListView - SP_FileDialogNewFolder = QtWidgets.QStyle.SP_FileDialogNewFolder - SP_FileDialogStart = QtWidgets.QStyle.SP_FileDialogStart - SP_FileDialogToParent = QtWidgets.QStyle.SP_FileDialogToParent - SP_FileIcon = QtWidgets.QStyle.SP_FileIcon - SP_FileLinkIcon = QtWidgets.QStyle.SP_FileLinkIcon - SP_MediaPause = QtWidgets.QStyle.SP_MediaPause - SP_MediaPlay = QtWidgets.QStyle.SP_MediaPlay - SP_MediaSeekBackward = QtWidgets.QStyle.SP_MediaSeekBackward - SP_MediaSeekForward = QtWidgets.QStyle.SP_MediaSeekForward - SP_MediaSkipBackward = QtWidgets.QStyle.SP_MediaSkipBackward - SP_MediaSkipForward = QtWidgets.QStyle.SP_MediaSkipForward - SP_MediaStop = QtWidgets.QStyle.SP_MediaStop - SP_MediaVolume = QtWidgets.QStyle.SP_MediaVolume - SP_MediaVolumeMuted = QtWidgets.QStyle.SP_MediaVolumeMuted - SP_LineEditClearButton = QtWidgets.QStyle.SP_LineEditClearButton - SP_DialogYesToAllButton = QtWidgets.QStyle.SP_DialogYesToAllButton - SP_DialogNoToAllButton = QtWidgets.QStyle.SP_DialogNoToAllButton - SP_DialogSaveAllButton = QtWidgets.QStyle.SP_DialogSaveAllButton - SP_DialogAbortButton = QtWidgets.QStyle.SP_DialogAbortButton - SP_DialogRetryButton = QtWidgets.QStyle.SP_DialogRetryButton - SP_DialogIgnoreButton = QtWidgets.QStyle.SP_DialogIgnoreButton - SP_RestoreDefaultsButton = QtWidgets.QStyle.SP_RestoreDefaultsButton - SP_MessageBoxCritical = QtWidgets.QStyle.SP_MessageBoxCritical - SP_MessageBoxInformation = QtWidgets.QStyle.SP_MessageBoxInformation - SP_MessageBoxQuestion = QtWidgets.QStyle.SP_MessageBoxQuestion - SP_MessageBoxWarning = QtWidgets.QStyle.SP_MessageBoxWarning - SP_TitleBarCloseButton = QtWidgets.QStyle.SP_TitleBarCloseButton - SP_TitleBarContextHelpButton = QtWidgets.QStyle.SP_TitleBarContextHelpButton - SP_TitleBarMaxButton = QtWidgets.QStyle.SP_TitleBarMaxButton - SP_TitleBarMenuButton = QtWidgets.QStyle.SP_TitleBarMenuButton - SP_TitleBarMinButton = QtWidgets.QStyle.SP_TitleBarMinButton - SP_TitleBarNormalButton = QtWidgets.QStyle.SP_TitleBarNormalButton - SP_TitleBarShadeButton = QtWidgets.QStyle.SP_TitleBarShadeButton - SP_TitleBarUnshadeButton = QtWidgets.QStyle.SP_TitleBarUnshadeButton - SP_ToolBarHorizontalExtensionButton = QtWidgets.QStyle.SP_ToolBarHorizontalExtensionButton - SP_ToolBarVerticalExtensionButton = QtWidgets.QStyle.SP_ToolBarVerticalExtensionButton - SP_TrashIcon = QtWidgets.QStyle.SP_TrashIcon - SP_VistaShield = QtWidgets.QStyle.SP_VistaShield - -# Need to fix an issue on Wayland on Linux: -# conda-forge does not support Wayland, for who knows what reason. -if sys.platform.lower().startswith('linux') and 'CONDA_PREFIX' in os.environ: - args.use_x11 = True - -if args.use_x11: - os.environ['XDG_SESSION_TYPE'] = 'x11' - -ICON_MAP = { - SP_TitleBarMinButton: 'minimize.svg', - SP_TitleBarMenuButton: 'menu.svg', - SP_TitleBarMaxButton: 'maximize.svg', - SP_TitleBarCloseButton: 'window_close.svg', - SP_TitleBarNormalButton: 'restore.svg', - SP_TitleBarShadeButton: 'shade.svg', - SP_TitleBarUnshadeButton: 'unshade.svg', - SP_TitleBarContextHelpButton: 'help.svg', - SP_MessageBoxInformation: 'message_information.svg', - SP_MessageBoxWarning: 'message_warning.svg', - SP_MessageBoxCritical: 'message_critical.svg', - SP_MessageBoxQuestion: 'message_question.svg', - SP_DesktopIcon: 'desktop.svg', - SP_TrashIcon: 'trash.svg', - SP_ComputerIcon: 'computer.svg', - SP_DriveFDIcon: 'floppy_drive.svg', - SP_DriveHDIcon: 'hard_drive.svg', - SP_DriveCDIcon: 'disc_drive.svg', - SP_DriveDVDIcon: 'disc_drive.svg', - SP_DriveNetIcon: 'network_drive.svg', - SP_DirHomeIcon: 'home_directory.svg', - SP_DirOpenIcon: 'folder_open.svg', - SP_DirClosedIcon: 'folder.svg', - SP_DirIcon: 'folder.svg', - SP_DirLinkIcon: 'folder_link.svg', - SP_DirLinkOpenIcon: 'folder_open_link.svg', - SP_FileIcon: 'file.svg', - SP_FileLinkIcon: 'file_link.svg', - SP_FileDialogStart: 'file_dialog_start.svg', - SP_FileDialogEnd: 'file_dialog_end.svg', - SP_FileDialogToParent: 'up_arrow.svg', - SP_FileDialogNewFolder: 'folder.svg', - SP_FileDialogDetailedView: 'file_dialog_detailed.svg', - SP_FileDialogInfoView: 'file_dialog_info.svg', - SP_FileDialogContentsView: 'file_dialog_contents.svg', - SP_FileDialogListView: 'file_dialog_list.svg', - SP_FileDialogBack: 'left_arrow.svg', - SP_DockWidgetCloseButton: 'close.svg', - SP_ToolBarHorizontalExtensionButton: 'horizontal_extension.svg', - SP_ToolBarVerticalExtensionButton: 'vertical_extension.svg', - SP_DialogOkButton: 'dialog_ok.svg', - SP_DialogCancelButton: 'dialog_cancel.svg', - SP_DialogHelpButton: 'dialog_help.svg', - SP_DialogOpenButton: 'dialog_open.svg', - SP_DialogSaveButton: 'dialog_save.svg', - SP_DialogCloseButton: 'dialog_close.svg', - SP_DialogApplyButton: 'dialog_apply.svg', - SP_DialogResetButton: 'dialog_reset.svg', - SP_DialogDiscardButton: 'dialog_discard.svg', - SP_DialogYesButton: 'dialog_apply.svg', - SP_DialogNoButton: 'dialog_no.svg', - SP_ArrowUp: 'up_arrow.svg', - SP_ArrowDown: 'down_arrow.svg', - SP_ArrowLeft: 'left_arrow.svg', - SP_ArrowRight: 'right_arrow.svg', - SP_ArrowBack: 'left_arrow.svg', - SP_ArrowForward: 'right_arrow.svg', - SP_CommandLink: 'right_arrow.svg', - SP_VistaShield: 'vista_shield.svg', - SP_BrowserReload: 'browser_refresh.svg', - SP_BrowserStop: 'browser_refresh_stop.svg', - SP_MediaPlay: 'play.svg', - SP_MediaStop: 'stop.svg', - SP_MediaPause: 'pause.svg', - SP_MediaSkipForward: 'skip_backward.svg', - SP_MediaSkipBackward: 'skip_forward.svg', - SP_MediaSeekForward: 'seek_forward.svg', - SP_MediaSeekBackward: 'seek_backward.svg', - SP_MediaVolume: 'volume.svg', - SP_MediaVolumeMuted: 'volume_muted.svg', - SP_LineEditClearButton: 'clear_text.svg', - SP_DialogYesToAllButton: 'dialog_yes_to_all.svg', - SP_DialogNoToAllButton: 'dialog_no.svg', - SP_DialogSaveAllButton: 'dialog_save_all.svg', - SP_DialogAbortButton: 'dialog_cancel.svg', - SP_DialogRetryButton: 'dialog_retry.svg', - SP_DialogIgnoreButton: 'dialog_ignore.svg', - SP_RestoreDefaultsButton: 'restore_defaults.svg', -} -if QtCore.QT_VERSION >= 393984: - ICON_MAP[SP_TabCloseButton] = 'tab_close.svg' - - -def standard_icon(widget, name): - '''Get the close icon depending on the stylesheet.''' - return widget.style().standardIcon(name) - - -def native_icon(style, icon, option=None, widget=None): - '''Get a standard icon for the native style''' - return style.standardIcon(icon, option, widget) - - -def stylesheet_icon(style, icon, option=None, widget=None): - '''Get a standard icon for the stylesheet style''' - - path = ICON_MAP[icon] - resource = f'{resource_format}{path}' - if QtCore.QFile.exists(resource): - return QtGui.QIcon(resource) - return QtWidgets.QCommonStyle.standardIcon(style, icon, option, widget) def style_icon(style, icon, option=None, widget=None): - if args.stylesheet == 'native': - return native_icon(style, icon, option, widget) - return stylesheet_icon(style, icon, option, widget) + return shared.style_icon(args, style, icon, ICON_MAP, option, widget) class ApplicationStyle(QtWidgets.QCommonStyle): @@ -410,7 +66,7 @@ def add_standard_button(ui, layout, icon, index): button = QtWidgets.QToolButton(ui.centralwidget) setattr(ui, f'button{index}', button) button.setAutoRaise(True) - button.setIcon(standard_icon(button, icon)) + button.setIcon(style_icon(button.style(), icon, widget=button)) button.setObjectName(f'button{index}') layout.addWidget(button) @@ -419,7 +75,8 @@ def add_standard_buttons(ui, page, icons): '''Create and add QToolButtons with standard icons to the UI.''' for icon_name in icons: - icon = standard_icon(page, globals()[icon_name]) + icon_enum = getattr(compat, icon_name) + icon = style_icon(page.style(), icon_enum, widget=page) item = QtWidgets.QListWidgetItem(icon, icon_name) page.addItem(item) @@ -434,7 +91,7 @@ class Ui: self.centralwidget.setObjectName('centralwidget') self.layout = QtWidgets.QVBoxLayout(self.centralwidget) self.layout.setObjectName('layout') - self.layout.setAlignment(AlignHCenter) + self.layout.setAlignment(compat.AlignHCenter) MainWindow.setCentralWidget(self.centralwidget) self.tool_box = QtWidgets.QToolBox(self.centralwidget) @@ -553,15 +210,15 @@ class Ui: self.comboBox.addItem('Second') self.verticalLayout.addWidget(self.comboBox) self.horizontalSlider = QtWidgets.QSlider(self.dockWidgetContents) - self.horizontalSlider.setOrientation(Horizontal) + self.horizontalSlider.setOrientation(compat.Horizontal) self.horizontalSlider.setObjectName('horizontalSlider') self.verticalLayout.addWidget(self.horizontalSlider) self.textEdit = QtWidgets.QTextEdit(self.dockWidgetContents) self.textEdit.setObjectName('textEdit') self.verticalLayout.addWidget(self.textEdit) self.line = QtWidgets.QFrame(self.dockWidgetContents) - self.line.setFrameShape(HLine) - self.line.setFrameShadow(Sunken) + self.line.setFrameShape(compat.HLine) + self.line.setFrameShadow(compat.Sunken) self.line.setObjectName('line') self.verticalLayout.addWidget(self.line) self.progressBar = QtWidgets.QProgressBar(self.dockWidgetContents) @@ -580,9 +237,9 @@ class Ui: self.statusbar.setObjectName('statusbar') MainWindow.setStatusBar(self.statusbar) - self.actionAction = QAction(MainWindow) + self.actionAction = compat.QAction(MainWindow) self.actionAction.setObjectName('actionAction') - self.actionAction_C = QAction(MainWindow) + self.actionAction_C = compat.QAction(MainWindow) self.actionAction_C.setObjectName('actionAction_C') self.menuMenu.addAction(self.actionAction) @@ -609,24 +266,7 @@ class Ui: def main(): 'Application entry point' - if args.scale != 1: - os.environ['QT_SCALE_FACTOR'] = str(args.scale) - else: - os.environ['QT_AUTO_SCREEN_SCALE_FACTOR'] = '1' - app = QtWidgets.QApplication(sys.argv[:1] + unknown) - window = QtWidgets.QMainWindow() - - if args.style != 'native': - style = QtWidgets.QStyleFactory.create(args.style) - app.setStyle(ApplicationStyle(style)) - - # use the default font size - font = app.font() - if args.font_size > 0: - font.setPointSizeF(args.font_size) - if args.font_family: - font.setFamily(args.font_family) - app.setFont(font) + app, window = shared.setup_app(args, unknown, compat, style_class=ApplicationStyle) # setup ui ui = Ui() @@ -637,19 +277,7 @@ def main(): ui.actionAction.triggered.connect(ui.about) ui.actionAction_C.triggered.connect(ui.critical) - # setup stylesheet - if args.stylesheet != 'native': - file = QtCore.QFile(stylesheet) - file.open(ReadOnly | Text) - stream = QtCore.QTextStream(file) - app.setStyleSheet(stream.readAll()) - - # run - window.show() - if args.pyqt6: - return app.exec() - else: - return app.exec_() + return shared.exec_app(args, app, window, compat) if __name__ == '__main__': sys.exit(main()) diff --git a/example/widgets.py b/example/widgets.py index e55c99e..f69333b 100644 --- a/example/widgets.py +++ b/example/widgets.py @@ -30,134 +30,22 @@ Simple example showing numerous built-in widgets. ''' -import argparse -import os +import shared import sys -example_dir = os.path.dirname(os.path.realpath(__file__)) -home = os.path.dirname(example_dir) -dist = os.path.join(home, 'dist') +parser = shared.create_parser() +args, unknown = shared.parse_args(parser) +QtCore, QtGui, QtWidgets = shared.import_qt(args) +compat = shared.get_compat_definitions(args) +ICON_MAP = shared.get_icon_map(args, compat) -# Create our arguments. -parser = argparse.ArgumentParser(description='Configurations for the Qt5 application.') -parser.add_argument( - '--stylesheet', - help='''stylesheet name''', - default='native' -) -# Know working styles include: -# 1. Fusion -# 2. Windows -parser.add_argument( - '--style', - help='''application style, which is different than the stylesheet''', - default='native' -) -parser.add_argument( - '--font-size', - help='''font size for the application''', - type=float, - default=-1 -) -parser.add_argument( - '--font-family', - help='''the font family''' -) -parser.add_argument( - '--scale', - help='''scale factor for the UI''', - type=float, - default=1, -) -parser.add_argument( - '--pyqt6', - help='''use PyQt6 rather than PyQt5.''', - action='store_true' -) -parser.add_argument( - '--use-x11', - help='''force the use of x11 on compatible systems.''', - action='store_true' -) - -args, unknown = parser.parse_known_args() -if args.pyqt6: - from PyQt6 import QtCore, QtGui, QtWidgets - QtCore.QDir.addSearchPath(args.stylesheet, f'{dist}/pyqt6/{args.stylesheet}/') - resource_format = f'{args.stylesheet}:' -else: - sys.path.insert(0, home) - from PyQt5 import QtCore, QtGui, QtWidgets - import breeze_resources - resource_format = f':/{args.stylesheet}/' -stylesheet = f'{resource_format}stylesheet.qss' - -# Compat definitions, between Qt5 and Qt6. -if args.pyqt6: - QAction = QtGui.QAction - Horizontal = QtCore.Qt.Orientation.Horizontal - Vertical = QtCore.Qt.Orientation.Vertical - TopToolBarArea = QtCore.Qt.ToolBarArea.TopToolBarArea - StyledPanel = QtWidgets.QFrame.Shape.StyledPanel - HLine = QtWidgets.QFrame.Shape.HLine - VLine = QtWidgets.QFrame.Shape.VLine - Raised = QtWidgets.QFrame.Shadow.Raised - Sunken = QtWidgets.QFrame.Shadow.Sunken - InstantPopup = QtWidgets.QToolButton.ToolButtonPopupMode.InstantPopup - MenuButtonPopup = QtWidgets.QToolButton.ToolButtonPopupMode.MenuButtonPopup - AlignTop = QtCore.Qt.AlignmentFlag.AlignTop - ItemIsUserCheckable = QtCore.Qt.ItemFlag.ItemIsUserCheckable - ItemIsUserTristate = QtCore.Qt.ItemFlag.ItemIsUserTristate - Checked = QtCore.Qt.CheckState.Checked - Unchecked = QtCore.Qt.CheckState.Unchecked - PartiallyChecked = QtCore.Qt.CheckState.PartiallyChecked - ReadOnly = QtCore.QFile.OpenModeFlag.ReadOnly - Text = QtCore.QFile.OpenModeFlag.Text - East = QtWidgets.QTabWidget.TabPosition.East - SP_DockWidgetCloseButton = QtWidgets.QStyle.StandardPixmap.SP_DockWidgetCloseButton - UpArrow = QtCore.Qt.ArrowType.UpArrow - Triangular = QtWidgets.QTabWidget.TabShape.Triangular - Password = QtWidgets.QLineEdit.EchoMode.Password -else: - QAction = QtWidgets.QAction - Horizontal = QtCore.Qt.Horizontal - Vertical = QtCore.Qt.Vertical - TopToolBarArea = QtCore.Qt.TopToolBarArea - StyledPanel = QtWidgets.QFrame.StyledPanel - HLine = QtWidgets.QFrame.HLine - VLine = QtWidgets.QFrame.VLine - Raised = QtWidgets.QFrame.Raised - Sunken = QtWidgets.QFrame.Sunken - InstantPopup = QtWidgets.QToolButton.InstantPopup - MenuButtonPopup = QtWidgets.QToolButton.MenuButtonPopup - AlignTop = QtCore.Qt.AlignTop - ItemIsUserCheckable = QtCore.Qt.ItemIsUserCheckable - ItemIsUserTristate = QtCore.Qt.ItemIsUserTristate - Checked = QtCore.Qt.Checked - Unchecked = QtCore.Qt.Unchecked - PartiallyChecked = QtCore.Qt.PartiallyChecked - ReadOnly = QtCore.QFile.ReadOnly - Text = QtCore.QFile.Text - East = QtWidgets.QTabWidget.East - SP_DockWidgetCloseButton = QtWidgets.QStyle.SP_DockWidgetCloseButton - UpArrow = QtCore.Qt.UpArrow - Triangular = QtWidgets.QTabWidget.Triangular - Password = QtWidgets.QLineEdit.Password - -# Need to fix an issue on Wayland on Linux: -# conda-forge does not support Wayland, for who knows what reason. -if sys.platform.lower().startswith('linux') and 'CONDA_PREFIX' in os.environ: - args.use_x11 = True - -if args.use_x11: - os.environ['XDG_SESSION_TYPE'] = 'x11' def close_icon(widget): '''Get the close icon depending on the stylesheet.''' - if args.stylesheet == 'native': - return widget.style().standardIcon(SP_DockWidgetCloseButton) - return QtGui.QIcon(f'{resource_format}close.svg') + style = widget.style() + icon = compat.SP_DockWidgetCloseButton + return shared.style_icon(args, style, icon, ICON_MAP, widget=widget) class Ui: @@ -171,7 +59,7 @@ class Ui: self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.centralwidget) self.verticalLayout_5.setObjectName('verticalLayout_5') self.tabWidget = QtWidgets.QTabWidget(self.centralwidget) - self.tabWidget.setTabPosition(East) + self.tabWidget.setTabPosition(compat.East) self.tabWidget.setTabsClosable(True) self.tabWidget.setObjectName('tabWidget') self.tab = QtWidgets.QWidget() @@ -326,17 +214,17 @@ class Ui: item_2 = QtWidgets.QTreeWidgetItem(item_1) item_2.setText(0, 'subitem') item_3 = QtWidgets.QTreeWidgetItem(item_2, ['Row 2.1']) - item_3.setFlags(item_3.flags() | ItemIsUserCheckable) - item_3.setCheckState(0, Unchecked) + item_3.setFlags(item_3.flags() | compat.ItemIsUserCheckable) + item_3.setCheckState(0, compat.Unchecked) item_4 = QtWidgets.QTreeWidgetItem(item_2, ['Row 2.2']) item_5 = QtWidgets.QTreeWidgetItem(item_4, ['Row 2.2.1']) item_6 = QtWidgets.QTreeWidgetItem(item_5, ['Row 2.2.1.1']) item_7 = QtWidgets.QTreeWidgetItem(item_5, ['Row 2.2.1.2']) - item_3.setFlags(item_7.flags() | ItemIsUserCheckable) - item_7.setCheckState(0, Checked) + item_3.setFlags(item_7.flags() | compat.ItemIsUserCheckable) + item_7.setCheckState(0, compat.Checked) item_8 = QtWidgets.QTreeWidgetItem(item_2, ['Row 2.3']) - item_8.setFlags(item_8.flags() | ItemIsUserTristate) - item_8.setCheckState(0, PartiallyChecked) + item_8.setFlags(item_8.flags() | compat.ItemIsUserTristate) + item_8.setCheckState(0, compat.PartiallyChecked) item_9 = QtWidgets.QTreeWidgetItem(self.treeWidget, ['Row 3']) item_10 = QtWidgets.QTreeWidgetItem(item_9, ['Row 3.1']) item_11 = QtWidgets.QTreeWidgetItem(self.treeWidget, ['Row 4']) @@ -351,7 +239,7 @@ class Ui: self.verticalLayout_4v2 = QtWidgets.QVBoxLayout(self.groupBox_3v2) self.verticalLayout_4v2.setObjectName('verticalLayout_4v2') self.tabWidget3 = QtWidgets.QTabWidget(self.tab_3v2) - self.tabWidget3.setTabShape(Triangular) + self.tabWidget3.setTabShape(compat.Triangular) self.gridLayout_3v2.setObjectName('tabWidget3') self.tab_1v3 = QtWidgets.QWidget() self.tab_2v3 = QtWidgets.QWidget() @@ -368,7 +256,7 @@ class Ui: self.line_3.setCompleter(completer) self.verticalLayout_6.addWidget(self.line_3) self.password = QtWidgets.QLineEdit('Sample', self.tab_1v3) - self.password.setEchoMode(Password) + self.password.setEchoMode(compat.Password) self.verticalLayout_6.addWidget(self.password) self.clear_line = QtWidgets.QLineEdit('Sample', self.tab_1v3) self.clear_line.setClearButtonEnabled(True) @@ -376,7 +264,7 @@ class Ui: self.lcd = QtWidgets.QLCDNumber(3, self.tab_1v3) self.lcd.display(15) self.verticalLayout_6.addWidget(self.lcd) - self.verticalLayout_4v2.addWidget(self.tabWidget3, 0, AlignTop) + self.verticalLayout_4v2.addWidget(self.tabWidget3, 0, compat.AlignTop) self.gridLayout_3v2.addWidget(self.groupBox_3v2, 0, 0, 1, 1) self.tabWidget.addTab(self.tab_2, '') self.tabWidget.addTab(self.tab_3v2, '') @@ -391,11 +279,11 @@ class Ui: self.bt_delay_popup.setObjectName('bt_delay_popup') self.horizontalLayout.addWidget(self.bt_delay_popup) self.bt_instant_popup = QtWidgets.QToolButton(self.centralwidget) - self.bt_instant_popup.setPopupMode(InstantPopup) + self.bt_instant_popup.setPopupMode(compat.InstantPopup) self.bt_instant_popup.setObjectName('bt_instant_popup') self.horizontalLayout.addWidget(self.bt_instant_popup) self.bt_menu_button_popup = QtWidgets.QToolButton(self.centralwidget) - self.bt_menu_button_popup.setPopupMode(MenuButtonPopup) + self.bt_menu_button_popup.setPopupMode(compat.MenuButtonPopup) self.bt_menu_button_popup.setObjectName('bt_menu_button_popup') self.horizontalLayout.addWidget(self.bt_menu_button_popup) self.bt_auto_raise = QtWidgets.QToolButton(self.centralwidget) @@ -405,12 +293,12 @@ class Ui: self.horizontalLayout.addWidget(self.bt_auto_raise) self.bt_arrow = QtWidgets.QToolButton(self.centralwidget) self.bt_arrow.setAutoRaise(True) - self.bt_arrow.setArrowType(UpArrow) + self.bt_arrow.setArrowType(compat.UpArrow) self.bt_arrow.setObjectName('bt_arrow') self.horizontalLayout.addWidget(self.bt_arrow) self.line_2 = QtWidgets.QFrame(self.centralwidget) - self.line_2.setFrameShape(VLine) - self.line_2.setFrameShadow(Sunken) + self.line_2.setFrameShape(compat.VLine) + self.line_2.setFrameShadow(compat.Sunken) self.line_2.setObjectName('line_2') self.horizontalLayout.addWidget(self.line_2) self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget) @@ -422,7 +310,7 @@ class Ui: self.doubleSpinBox.setObjectName('doubleSpinBox') self.horizontalLayout.addWidget(self.doubleSpinBox) self.toolButton = QtWidgets.QToolButton(self.centralwidget) - self.toolButton.setPopupMode(InstantPopup) + self.toolButton.setPopupMode(compat.InstantPopup) self.toolButton.setObjectName('toolButton') self.horizontalLayout.addWidget(self.toolButton) self.verticalLayout_5.addLayout(self.horizontalLayout) @@ -453,15 +341,15 @@ class Ui: self.comboBox.addItem('') self.verticalLayout.addWidget(self.comboBox) self.horizontalSlider = QtWidgets.QSlider(self.dockWidgetContents) - self.horizontalSlider.setOrientation(Horizontal) + self.horizontalSlider.setOrientation(compat.Horizontal) self.horizontalSlider.setObjectName('horizontalSlider') self.verticalLayout.addWidget(self.horizontalSlider) self.textEdit = QtWidgets.QTextEdit(self.dockWidgetContents) self.textEdit.setObjectName('textEdit') self.verticalLayout.addWidget(self.textEdit) self.line = QtWidgets.QFrame(self.dockWidgetContents) - self.line.setFrameShape(HLine) - self.line.setFrameShadow(Sunken) + self.line.setFrameShape(compat.HLine) + self.line.setFrameShadow(compat.Sunken) self.line.setObjectName('line') self.verticalLayout.addWidget(self.line) self.progressBar = QtWidgets.QProgressBar(self.dockWidgetContents) @@ -471,8 +359,8 @@ class Ui: self.verticalLayout_2.addLayout(self.verticalLayout) self.frame = QtWidgets.QFrame(self.dockWidgetContents) self.frame.setMinimumSize(QtCore.QSize(0, 100)) - self.frame.setFrameShape(StyledPanel) - self.frame.setFrameShadow(Raised) + self.frame.setFrameShape(compat.StyledPanel) + self.frame.setFrameShadow(compat.Raised) self.frame.setLineWidth(3) self.frame.setObjectName('frame') self.verticalLayout_2.addWidget(self.frame) @@ -480,7 +368,7 @@ class Ui: MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(1), self.dockWidget1) self.toolBar = QtWidgets.QToolBar(MainWindow) self.toolBar.setObjectName('toolBar') - MainWindow.addToolBar(TopToolBarArea, self.toolBar) + MainWindow.addToolBar(compat.TopToolBarArea, self.toolBar) self.dockWidget2 = QtWidgets.QDockWidget(MainWindow) self.dockWidget2.setObjectName('dockWidget2') self.dockWidgetContents_2 = QtWidgets.QWidget() @@ -488,16 +376,16 @@ class Ui: self.gridLayout_3 = QtWidgets.QGridLayout(self.dockWidgetContents_2) self.gridLayout_3.setObjectName('gridLayout_3') self.verticalSlider = QtWidgets.QSlider(self.dockWidgetContents_2) - self.verticalSlider.setOrientation(Vertical) + self.verticalSlider.setOrientation(compat.Vertical) self.verticalSlider.setObjectName('verticalSlider') self.gridLayout_3.addWidget(self.verticalSlider, 0, 0, 1, 1) self.dockWidget2.setWidget(self.dockWidgetContents_2) MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(1), self.dockWidget2) - self.actionAction = QAction(MainWindow) + self.actionAction = compat.QAction(MainWindow) self.actionAction.setObjectName('actionAction') - self.actionSub_menu = QAction(MainWindow) + self.actionSub_menu = compat.QAction(MainWindow) self.actionSub_menu.setObjectName('actionSub_menu') - self.actionAction_C = QAction(MainWindow) + self.actionAction_C = compat.QAction(MainWindow) self.actionAction_C.setObjectName('actionAction_C') self.menuSubmenu_2.addAction(self.actionSub_menu) self.menuSubmenu_2.addAction(self.actionAction_C) @@ -624,25 +512,7 @@ class Ui: def main(): 'Application entry point' - if args.scale != 1: - os.environ['QT_SCALE_FACTOR'] = str(args.scale) - else: - os.environ['QT_AUTO_SCREEN_SCALE_FACTOR'] = '1' - - app = QtWidgets.QApplication(sys.argv[:1] + unknown) - if args.style != 'native': - style = QtWidgets.QStyleFactory.create(args.style) - app.setStyle(style) - - window = QtWidgets.QMainWindow() - - # use the default font size - font = app.font() - if args.font_size > 0: - font.setPointSizeF(args.font_size) - if args.font_family: - font.setFamily(args.font_family) - app.setFont(font) + app, window = shared.setup_app(args, unknown, compat) # setup ui ui = Ui() @@ -668,19 +538,7 @@ def main(): # tabify dock widgets to show bug #6 window.tabifyDockWidget(ui.dockWidget1, ui.dockWidget2) - # setup stylesheet - if args.stylesheet != 'native': - file = QtCore.QFile(stylesheet) - file.open(ReadOnly | Text) - stream = QtCore.QTextStream(file) - app.setStyleSheet(stream.readAll()) - - # run - window.show() - if args.pyqt6: - return app.exec() - else: - return app.exec_() + return shared.exec_app(args, app, window, compat) if __name__ == '__main__':