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.
main
Alex Huszagh 2022-05-03 12:43:49 -05:00
parent 7117f45ef8
commit 48bd6fb47d
8 changed files with 736 additions and 1089 deletions

View File

@ -223,12 +223,6 @@ class ApplicationStyle(QtWidgets.QCommonStyle):
def main(): def main():
app = QtWidgets.QApplication(sys.argv) 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, # Install our custom style globally. QCommonStyle, unlike QProxyStyle,
# actually works nicely with stylesheets. `Fusion` is available # actually works nicely with stylesheets. `Fusion` is available
# on all platforms, but you can use any style you want. We # on all platforms, but you can use any style you want. We
@ -237,6 +231,13 @@ def main():
style = QtWidgets.QStyleFactory.create('Fusion') style = QtWidgets.QStyleFactory.create('Fusion')
app.setStyle(ApplicationStyle(style)) 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() return app.exec()

View File

@ -29,125 +29,26 @@
Simple PyQt application using the advanced-docking-system. Simple PyQt application using the advanced-docking-system.
''' '''
import argparse import shared
import os
import sys import sys
example_dir = os.path.dirname(os.path.realpath(__file__)) parser = shared.create_parser()
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( parser.add_argument(
'--use-internal', '--use-internal',
help='''use the dock manager internal stylesheet.''', help='''use the dock manager internal stylesheet.''',
action='store_true' action='store_true'
) )
parser.add_argument( args, unknown = shared.parse_args(parser)
'--use-x11', QtCore, QtGui, QtWidgets = shared.import_qt(args)
help='''force the use of x11 on compatible systems.''', compat = shared.get_compat_definitions(args)
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'
from PyQtAds import QtAds 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(): def main():
'Application entry point' 'Application entry point'
if args.scale != 1: app, window = shared.setup_app(args, unknown, compat)
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())
# setup the dock manager # setup the dock manager
window.setObjectName('MainWindow') window.setObjectName('MainWindow')
@ -156,12 +57,14 @@ def main():
window.setCentralWidget(widget) window.setCentralWidget(widget)
dock_manager = QtAds.CDockManager(window) dock_manager = QtAds.CDockManager(window)
DockArea = QtAds.DockWidgetArea
# add widgets to the dock manager # add widgets to the dock manager
label_widget = QtAds.CDockWidget('Dock') label_widget = QtAds.CDockWidget('Dock')
label = QtWidgets.QLabel('Some label') label = QtWidgets.QLabel('Some label')
label_widget.setWidget(label) label_widget.setWidget(label)
dock_area = dock_manager.setCentralWidget(label_widget) dock_area = dock_manager.setCentralWidget(label_widget)
dock_area.setAllowedAreas(QtAds.DockWidgetArea.OuterDockAreas) dock_area.setAllowedAreas(DockArea.OuterDockAreas)
list_widget = QtAds.CDockWidget('List') list_widget = QtAds.CDockWidget('List')
lst = QtWidgets.QListWidget() lst = QtWidgets.QListWidget()
@ -169,7 +72,7 @@ def main():
lst.addItem(QtWidgets.QListWidgetItem(f'Item {index + 1}')) lst.addItem(QtWidgets.QListWidgetItem(f'Item {index + 1}'))
list_widget.setWidget(lst) list_widget.setWidget(lst)
list_widget.setMinimumSizeHintMode(QtAds.CDockWidget.MinimumSizeHintFromDockWidget) 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_widget = QtAds.CDockWidget('Table')
table = QtWidgets.QTableWidget() table = QtWidgets.QTableWidget()
@ -178,18 +81,14 @@ def main():
table.setRowCount(40) table.setRowCount(40)
table_widget.setWidget(table) table_widget.setWidget(table)
table_widget.setMinimumSizeHintMode(QtAds.CDockWidget.MinimumSizeHintFromDockWidget) 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: if not args.use_internal:
dock_manager.setStyleSheet('') dock_manager.setStyleSheet('')
# run # run
window.setWindowState(WindowMaximized) window.setWindowState(compat.WindowMaximized)
window.show() return shared.exec_app(args, app, window, compat)
if args.pyqt6:
return app.exec()
else:
return app.exec_()
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(main()) sys.exit(main())

View File

@ -31,123 +31,20 @@
supports highlighting the handle on the active or hovered dial. supports highlighting the handle on the active or hovered dial.
''' '''
import argparse
import math import math
import os import shared
import sys import sys
example_dir = os.path.dirname(os.path.realpath(__file__)) parser = shared.create_parser()
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.add_argument( parser.add_argument(
'--no-align', '--no-align',
help='''allow larger widgets without forcing alignment.''', help='''allow larger widgets without forcing alignment.''',
action='store_true' action='store_true'
) )
args, unknown = shared.parse_args(parser)
args, unknown = parser.parse_known_args() QtCore, QtGui, QtWidgets = shared.import_qt(args)
if args.pyqt6: compat = shared.get_compat_definitions(args)
from PyQt6 import QtCore, QtGui, QtWidgets colors = shared.get_colors(args, compat)
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)
def radius(dial): def radius(dial):
@ -209,7 +106,13 @@ def default_pen(color, width):
def round_pen(color, width): def round_pen(color, width):
'''Create a pen with round join styles.''' '''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): def event_pos(event):
'''Determine the event position.''' '''Determine the event position.'''
@ -238,12 +141,12 @@ class Dial(QtWidgets.QDial):
self.notch_start = self.groove_width + 2 self.notch_start = self.groove_width + 2
self.notch_end = self.notch_start + 2 self.notch_end = self.notch_start + 2
self.notch_width = 2 self.notch_width = 2
self.groove_bd_color = GROOVE_BORDER self.groove_bd_color = colors.GrooveBorder
self.groove_bg_color = GROOVE_BACKGROUND self.groove_bg_color = colors.GrooveBackground
self.handle_bg_color = HANDLE_BACKGROUND self.handle_bg_color = colors.HandleBackground
self.handle_bd_color = HANDLE_BORDER self.handle_bd_color = colors.HandleBorder
self.notch_color = NOTCH self.notch_color = colors.Notch
self.selected_color = SELECTED self.selected_color = colors.Selected
# Store some state changes. # Store some state changes.
self.groove = (0, 0) self.groove = (0, 0)
@ -262,7 +165,7 @@ class Dial(QtWidgets.QDial):
# Get our item colors. Override the color when selected/active. # Get our item colors. Override the color when selected/active.
handle_bd_color = self.handle_bd_color handle_bd_color = self.handle_bd_color
mask = State_HasFocus | State_Selected mask = compat.State_HasFocus | compat.State_Selected
# WindowActive # WindowActive
if options.state & mask or self.is_hovered: if options.state & mask or self.is_hovered:
handle_bd_color = self.selected_color 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, # 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 # rather than calculate if it's actually in the circle. This won't
# matter except if the dial is scaled by a large amount. # 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 x0 = self.handle[0] - self.handle_radius
y0 = self.handle[1] - self.handle_radius y0 = self.handle[1] - self.handle_radius
size = 2 * self.handle_radius size = 2 * self.handle_radius
rect = QtCore.QRectF(x0, y0, size, size) rect = QtCore.QRectF(x0, y0, size, size)
self.is_hovered = rect.contains(event_pos(event)) self.is_hovered = rect.contains(event_pos(event))
self.repaint() self.repaint()
elif event.type() == HoverLeave: elif event.type() == compat.HoverLeave:
self.is_hovered = False self.is_hovered = False
self.repaint() self.repaint()
@ -372,7 +275,7 @@ class Ui:
self.layout = QtWidgets.QVBoxLayout(self.centralwidget) self.layout = QtWidgets.QVBoxLayout(self.centralwidget)
self.layout.setObjectName('layout') self.layout.setObjectName('layout')
if not args.no_align: if not args.no_align:
self.layout.setAlignment(AlignHCenter) self.layout.setAlignment(compat.AlignHCenter)
MainWindow.setCentralWidget(self.centralwidget) MainWindow.setCentralWidget(self.centralwidget)
self.dial1 = Dial(self.centralwidget) self.dial1 = Dial(self.centralwidget)
@ -390,44 +293,14 @@ class Ui:
def main(): def main():
'Application entry point' 'Application entry point'
if args.scale != 1: app, window = shared.setup_app(args, unknown, compat)
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()
# setup ui # setup ui
ui = Ui() ui = Ui()
ui.setup(window) ui.setup(window)
window.setWindowTitle('QDial') window.setWindowTitle('QDial')
# use the default font size return shared.exec_app(args, app, window, compat)
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_()
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(main()) sys.exit(main())

View File

@ -33,55 +33,10 @@
and palette edits correctly affect styles in Qt5, but not Qt6. and palette edits correctly affect styles in Qt5, but not Qt6.
''' '''
import argparse import shared
import os
import sys import sys
example_dir = os.path.dirname(os.path.realpath(__file__)) parser = shared.create_parser()
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.add_argument( parser.add_argument(
'--set-app-palette', '--set-app-palette',
help='''set the placeholder text palette globally.''', help='''set the placeholder text palette globally.''',
@ -92,38 +47,11 @@ parser.add_argument(
help='''set the placeholder text palette for the affected widgets.''', help='''set the placeholder text palette for the affected widgets.''',
action='store_true' 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): def set_palette(widget, role, color):
'''Set the palette for the placeholder text. This only works in Qt5.''' '''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) widget.setPalette(palette)
def set_placeholder_palette(widget): def set_placeholder_palette(widget):
set_palette(widget, PlaceholderText, PLACEHOLDER_COLOR) set_palette(widget, compat.PlaceholderText, colors.PlaceholderColor)
class Ui: class Ui:
@ -146,7 +74,7 @@ class Ui:
self.centralwidget.setObjectName('centralwidget') self.centralwidget.setObjectName('centralwidget')
self.layout = QtWidgets.QVBoxLayout(self.centralwidget) self.layout = QtWidgets.QVBoxLayout(self.centralwidget)
self.layout.setObjectName('layout') self.layout.setObjectName('layout')
self.layout.setAlignment(AlignHCenter) self.layout.setAlignment(compat.AlignHCenter)
MainWindow.setCentralWidget(self.centralwidget) MainWindow.setCentralWidget(self.centralwidget)
self.textEdit = QtWidgets.QTextEdit(self.centralwidget) self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
@ -172,46 +100,16 @@ class Ui:
def main(): def main():
'Application entry point' 'Application entry point'
if args.scale != 1: app, window = shared.setup_app(args, unknown, compat)
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)
if args.set_app_palette: if args.set_app_palette:
set_placeholder_palette(app) set_placeholder_palette(app)
window = QtWidgets.QMainWindow()
# setup ui # setup ui
ui = Ui() ui = Ui()
ui.setup(window) ui.setup(window)
window.setWindowTitle('Stylized Placeholder Text.') window.setWindowTitle('Stylized Placeholder Text.')
# use the default font size return shared.exec_app(args, app, window, compat)
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_()
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(main()) sys.exit(main())

600
example/shared.py Normal file
View File

@ -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)

View File

@ -31,99 +31,14 @@
get customized styling behavior with a QSlider. get customized styling behavior with a QSlider.
''' '''
import argparse import shared
import os
import sys import sys
example_dir = os.path.dirname(os.path.realpath(__file__)) parser = shared.create_parser()
home = os.path.dirname(example_dir) args, unknown = shared.parse_args(parser)
dist = os.path.join(home, 'dist') QtCore, QtGui, QtWidgets = shared.import_qt(args)
compat = shared.get_compat_definitions(args)
# Create our arguments. colors = shared.get_colors(args, compat)
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)
class Slider(QtWidgets.QSlider): class Slider(QtWidgets.QSlider):
@ -140,31 +55,36 @@ class Slider(QtWidgets.QSlider):
self.initStyleOption(options) self.initStyleOption(options)
style = self.style() 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() interval = self.tickInterval() or self.pageStep()
position = self.tickPosition() position = self.tickPosition()
if position != NoTicks and interval != 0: if position != compat.NoTicks and interval != 0:
minimum = self.minimum() minimum = self.minimum()
maximum = self.maximum() maximum = self.maximum()
painter.setPen(TICK_COLOR) painter.setPen(colors.TickColor)
for i in range(minimum, maximum + interval, interval): for i in range(minimum, maximum + interval, interval):
percent = (i - minimum) / (maximum - minimum + 1) + 0.005 percent = (i - minimum) / (maximum - minimum + 1) + 0.005
width = (self.width() - handle.width()) + handle.width() / 2 width = (self.width() - handle.width()) + handle.width() / 2
x = int(percent * width) x = int(percent * width)
h = 4 h = 4
if position == TicksBothSides or position == TicksAbove: if position == compat.TicksBothSides or position == compat.TicksAbove:
y = self.rect().top() y = self.rect().top()
painter.drawLine(x, y, x, y + h) 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() y = self.rect().bottom()
painter.drawLine(x, y, x, y - h) painter.drawLine(x, y, x, y - h)
options.subControls = SC_SliderGroove options.subControls = compat.SC_SliderGroove
painter.drawComplexControl(CC_Slider, options) painter.drawComplexControl(compat.CC_Slider, options)
options.subControls = SC_SliderHandle options.subControls = compat.SC_SliderHandle
painter.drawComplexControl(CC_Slider, options) painter.drawComplexControl(compat.CC_Slider, options)
class Ui: class Ui:
@ -177,13 +97,13 @@ class Ui:
self.centralwidget.setObjectName('centralwidget') self.centralwidget.setObjectName('centralwidget')
self.layout = QtWidgets.QVBoxLayout(self.centralwidget) self.layout = QtWidgets.QVBoxLayout(self.centralwidget)
self.layout.setObjectName('layout') self.layout.setObjectName('layout')
self.layout.setAlignment(AlignHCenter) self.layout.setAlignment(compat.AlignHCenter)
MainWindow.setCentralWidget(self.centralwidget) MainWindow.setCentralWidget(self.centralwidget)
self.slider = Slider(self.centralwidget) self.slider = Slider(self.centralwidget)
self.slider.setOrientation(Horizontal) self.slider.setOrientation(compat.Horizontal)
self.slider.setTickInterval(5) self.slider.setTickInterval(5)
self.slider.setTickPosition(TicksAbove) self.slider.setTickPosition(compat.TicksAbove)
self.slider.setObjectName('slider') self.slider.setObjectName('slider')
self.layout.addWidget(self.slider) self.layout.addWidget(self.slider)
@ -191,44 +111,14 @@ class Ui:
def main(): def main():
'Application entry point' 'Application entry point'
if args.scale != 1: app, window = shared.setup_app(args, unknown, compat)
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()
# setup ui # setup ui
ui = Ui() ui = Ui()
ui.setup(window) ui.setup(window)
window.setWindowTitle('QSlider with Ticks.') window.setWindowTitle('QSlider with Ticks.')
# use the default font size return shared.exec_app(args, app, window, compat)
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_()
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(main()) sys.exit(main())

View File

@ -2,8 +2,7 @@
# #
# The MIT License (MIT) # The MIT License (MIT)
# #
# Copyright (c) <2013-2014> <Colin Duquesnoy> # Copyright (c) <2022-Present> <Alex Huszagh>
# Modified by Alex Huszagh
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the 'Software'), to deal # of this software and associated documentation files (the 'Software'), to deal
@ -30,361 +29,18 @@
Example overriding QCommonStyle for custom standard icons. Example overriding QCommonStyle for custom standard icons.
''' '''
import argparse import shared
import os
import sys import sys
example_dir = os.path.dirname(os.path.realpath(__file__)) parser = shared.create_parser()
home = os.path.dirname(example_dir) args, unknown = shared.parse_args(parser)
dist = os.path.join(home, 'dist') 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): def style_icon(style, icon, option=None, widget=None):
if args.stylesheet == 'native': return shared.style_icon(args, style, icon, ICON_MAP, option, widget)
return native_icon(style, icon, option, widget)
return stylesheet_icon(style, icon, option, widget)
class ApplicationStyle(QtWidgets.QCommonStyle): class ApplicationStyle(QtWidgets.QCommonStyle):
@ -410,7 +66,7 @@ def add_standard_button(ui, layout, icon, index):
button = QtWidgets.QToolButton(ui.centralwidget) button = QtWidgets.QToolButton(ui.centralwidget)
setattr(ui, f'button{index}', button) setattr(ui, f'button{index}', button)
button.setAutoRaise(True) button.setAutoRaise(True)
button.setIcon(standard_icon(button, icon)) button.setIcon(style_icon(button.style(), icon, widget=button))
button.setObjectName(f'button{index}') button.setObjectName(f'button{index}')
layout.addWidget(button) layout.addWidget(button)
@ -419,7 +75,8 @@ def add_standard_buttons(ui, page, icons):
'''Create and add QToolButtons with standard icons to the UI.''' '''Create and add QToolButtons with standard icons to the UI.'''
for icon_name in icons: 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) item = QtWidgets.QListWidgetItem(icon, icon_name)
page.addItem(item) page.addItem(item)
@ -434,7 +91,7 @@ class Ui:
self.centralwidget.setObjectName('centralwidget') self.centralwidget.setObjectName('centralwidget')
self.layout = QtWidgets.QVBoxLayout(self.centralwidget) self.layout = QtWidgets.QVBoxLayout(self.centralwidget)
self.layout.setObjectName('layout') self.layout.setObjectName('layout')
self.layout.setAlignment(AlignHCenter) self.layout.setAlignment(compat.AlignHCenter)
MainWindow.setCentralWidget(self.centralwidget) MainWindow.setCentralWidget(self.centralwidget)
self.tool_box = QtWidgets.QToolBox(self.centralwidget) self.tool_box = QtWidgets.QToolBox(self.centralwidget)
@ -553,15 +210,15 @@ class Ui:
self.comboBox.addItem('Second') self.comboBox.addItem('Second')
self.verticalLayout.addWidget(self.comboBox) self.verticalLayout.addWidget(self.comboBox)
self.horizontalSlider = QtWidgets.QSlider(self.dockWidgetContents) self.horizontalSlider = QtWidgets.QSlider(self.dockWidgetContents)
self.horizontalSlider.setOrientation(Horizontal) self.horizontalSlider.setOrientation(compat.Horizontal)
self.horizontalSlider.setObjectName('horizontalSlider') self.horizontalSlider.setObjectName('horizontalSlider')
self.verticalLayout.addWidget(self.horizontalSlider) self.verticalLayout.addWidget(self.horizontalSlider)
self.textEdit = QtWidgets.QTextEdit(self.dockWidgetContents) self.textEdit = QtWidgets.QTextEdit(self.dockWidgetContents)
self.textEdit.setObjectName('textEdit') self.textEdit.setObjectName('textEdit')
self.verticalLayout.addWidget(self.textEdit) self.verticalLayout.addWidget(self.textEdit)
self.line = QtWidgets.QFrame(self.dockWidgetContents) self.line = QtWidgets.QFrame(self.dockWidgetContents)
self.line.setFrameShape(HLine) self.line.setFrameShape(compat.HLine)
self.line.setFrameShadow(Sunken) self.line.setFrameShadow(compat.Sunken)
self.line.setObjectName('line') self.line.setObjectName('line')
self.verticalLayout.addWidget(self.line) self.verticalLayout.addWidget(self.line)
self.progressBar = QtWidgets.QProgressBar(self.dockWidgetContents) self.progressBar = QtWidgets.QProgressBar(self.dockWidgetContents)
@ -580,9 +237,9 @@ class Ui:
self.statusbar.setObjectName('statusbar') self.statusbar.setObjectName('statusbar')
MainWindow.setStatusBar(self.statusbar) MainWindow.setStatusBar(self.statusbar)
self.actionAction = QAction(MainWindow) self.actionAction = compat.QAction(MainWindow)
self.actionAction.setObjectName('actionAction') self.actionAction.setObjectName('actionAction')
self.actionAction_C = QAction(MainWindow) self.actionAction_C = compat.QAction(MainWindow)
self.actionAction_C.setObjectName('actionAction_C') self.actionAction_C.setObjectName('actionAction_C')
self.menuMenu.addAction(self.actionAction) self.menuMenu.addAction(self.actionAction)
@ -609,24 +266,7 @@ class Ui:
def main(): def main():
'Application entry point' 'Application entry point'
if args.scale != 1: app, window = shared.setup_app(args, unknown, compat, style_class=ApplicationStyle)
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)
# setup ui # setup ui
ui = Ui() ui = Ui()
@ -637,19 +277,7 @@ def main():
ui.actionAction.triggered.connect(ui.about) ui.actionAction.triggered.connect(ui.about)
ui.actionAction_C.triggered.connect(ui.critical) ui.actionAction_C.triggered.connect(ui.critical)
# setup stylesheet return shared.exec_app(args, app, window, compat)
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_()
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(main()) sys.exit(main())

View File

@ -30,134 +30,22 @@
Simple example showing numerous built-in widgets. Simple example showing numerous built-in widgets.
''' '''
import argparse import shared
import os
import sys import sys
example_dir = os.path.dirname(os.path.realpath(__file__)) parser = shared.create_parser()
home = os.path.dirname(example_dir) args, unknown = shared.parse_args(parser)
dist = os.path.join(home, 'dist') 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): def close_icon(widget):
'''Get the close icon depending on the stylesheet.''' '''Get the close icon depending on the stylesheet.'''
if args.stylesheet == 'native': style = widget.style()
return widget.style().standardIcon(SP_DockWidgetCloseButton) icon = compat.SP_DockWidgetCloseButton
return QtGui.QIcon(f'{resource_format}close.svg') return shared.style_icon(args, style, icon, ICON_MAP, widget=widget)
class Ui: class Ui:
@ -171,7 +59,7 @@ class Ui:
self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.centralwidget) self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout_5.setObjectName('verticalLayout_5') self.verticalLayout_5.setObjectName('verticalLayout_5')
self.tabWidget = QtWidgets.QTabWidget(self.centralwidget) self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
self.tabWidget.setTabPosition(East) self.tabWidget.setTabPosition(compat.East)
self.tabWidget.setTabsClosable(True) self.tabWidget.setTabsClosable(True)
self.tabWidget.setObjectName('tabWidget') self.tabWidget.setObjectName('tabWidget')
self.tab = QtWidgets.QWidget() self.tab = QtWidgets.QWidget()
@ -326,17 +214,17 @@ class Ui:
item_2 = QtWidgets.QTreeWidgetItem(item_1) item_2 = QtWidgets.QTreeWidgetItem(item_1)
item_2.setText(0, 'subitem') item_2.setText(0, 'subitem')
item_3 = QtWidgets.QTreeWidgetItem(item_2, ['Row 2.1']) item_3 = QtWidgets.QTreeWidgetItem(item_2, ['Row 2.1'])
item_3.setFlags(item_3.flags() | ItemIsUserCheckable) item_3.setFlags(item_3.flags() | compat.ItemIsUserCheckable)
item_3.setCheckState(0, Unchecked) item_3.setCheckState(0, compat.Unchecked)
item_4 = QtWidgets.QTreeWidgetItem(item_2, ['Row 2.2']) item_4 = QtWidgets.QTreeWidgetItem(item_2, ['Row 2.2'])
item_5 = QtWidgets.QTreeWidgetItem(item_4, ['Row 2.2.1']) item_5 = QtWidgets.QTreeWidgetItem(item_4, ['Row 2.2.1'])
item_6 = QtWidgets.QTreeWidgetItem(item_5, ['Row 2.2.1.1']) item_6 = QtWidgets.QTreeWidgetItem(item_5, ['Row 2.2.1.1'])
item_7 = QtWidgets.QTreeWidgetItem(item_5, ['Row 2.2.1.2']) item_7 = QtWidgets.QTreeWidgetItem(item_5, ['Row 2.2.1.2'])
item_3.setFlags(item_7.flags() | ItemIsUserCheckable) item_3.setFlags(item_7.flags() | compat.ItemIsUserCheckable)
item_7.setCheckState(0, Checked) item_7.setCheckState(0, compat.Checked)
item_8 = QtWidgets.QTreeWidgetItem(item_2, ['Row 2.3']) item_8 = QtWidgets.QTreeWidgetItem(item_2, ['Row 2.3'])
item_8.setFlags(item_8.flags() | ItemIsUserTristate) item_8.setFlags(item_8.flags() | compat.ItemIsUserTristate)
item_8.setCheckState(0, PartiallyChecked) item_8.setCheckState(0, compat.PartiallyChecked)
item_9 = QtWidgets.QTreeWidgetItem(self.treeWidget, ['Row 3']) item_9 = QtWidgets.QTreeWidgetItem(self.treeWidget, ['Row 3'])
item_10 = QtWidgets.QTreeWidgetItem(item_9, ['Row 3.1']) item_10 = QtWidgets.QTreeWidgetItem(item_9, ['Row 3.1'])
item_11 = QtWidgets.QTreeWidgetItem(self.treeWidget, ['Row 4']) 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 = QtWidgets.QVBoxLayout(self.groupBox_3v2)
self.verticalLayout_4v2.setObjectName('verticalLayout_4v2') self.verticalLayout_4v2.setObjectName('verticalLayout_4v2')
self.tabWidget3 = QtWidgets.QTabWidget(self.tab_3v2) self.tabWidget3 = QtWidgets.QTabWidget(self.tab_3v2)
self.tabWidget3.setTabShape(Triangular) self.tabWidget3.setTabShape(compat.Triangular)
self.gridLayout_3v2.setObjectName('tabWidget3') self.gridLayout_3v2.setObjectName('tabWidget3')
self.tab_1v3 = QtWidgets.QWidget() self.tab_1v3 = QtWidgets.QWidget()
self.tab_2v3 = QtWidgets.QWidget() self.tab_2v3 = QtWidgets.QWidget()
@ -368,7 +256,7 @@ class Ui:
self.line_3.setCompleter(completer) self.line_3.setCompleter(completer)
self.verticalLayout_6.addWidget(self.line_3) self.verticalLayout_6.addWidget(self.line_3)
self.password = QtWidgets.QLineEdit('Sample', self.tab_1v3) self.password = QtWidgets.QLineEdit('Sample', self.tab_1v3)
self.password.setEchoMode(Password) self.password.setEchoMode(compat.Password)
self.verticalLayout_6.addWidget(self.password) self.verticalLayout_6.addWidget(self.password)
self.clear_line = QtWidgets.QLineEdit('Sample', self.tab_1v3) self.clear_line = QtWidgets.QLineEdit('Sample', self.tab_1v3)
self.clear_line.setClearButtonEnabled(True) self.clear_line.setClearButtonEnabled(True)
@ -376,7 +264,7 @@ class Ui:
self.lcd = QtWidgets.QLCDNumber(3, self.tab_1v3) self.lcd = QtWidgets.QLCDNumber(3, self.tab_1v3)
self.lcd.display(15) self.lcd.display(15)
self.verticalLayout_6.addWidget(self.lcd) 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.gridLayout_3v2.addWidget(self.groupBox_3v2, 0, 0, 1, 1)
self.tabWidget.addTab(self.tab_2, '') self.tabWidget.addTab(self.tab_2, '')
self.tabWidget.addTab(self.tab_3v2, '') self.tabWidget.addTab(self.tab_3v2, '')
@ -391,11 +279,11 @@ class Ui:
self.bt_delay_popup.setObjectName('bt_delay_popup') self.bt_delay_popup.setObjectName('bt_delay_popup')
self.horizontalLayout.addWidget(self.bt_delay_popup) self.horizontalLayout.addWidget(self.bt_delay_popup)
self.bt_instant_popup = QtWidgets.QToolButton(self.centralwidget) 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.bt_instant_popup.setObjectName('bt_instant_popup')
self.horizontalLayout.addWidget(self.bt_instant_popup) self.horizontalLayout.addWidget(self.bt_instant_popup)
self.bt_menu_button_popup = QtWidgets.QToolButton(self.centralwidget) 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.bt_menu_button_popup.setObjectName('bt_menu_button_popup')
self.horizontalLayout.addWidget(self.bt_menu_button_popup) self.horizontalLayout.addWidget(self.bt_menu_button_popup)
self.bt_auto_raise = QtWidgets.QToolButton(self.centralwidget) self.bt_auto_raise = QtWidgets.QToolButton(self.centralwidget)
@ -405,12 +293,12 @@ class Ui:
self.horizontalLayout.addWidget(self.bt_auto_raise) self.horizontalLayout.addWidget(self.bt_auto_raise)
self.bt_arrow = QtWidgets.QToolButton(self.centralwidget) self.bt_arrow = QtWidgets.QToolButton(self.centralwidget)
self.bt_arrow.setAutoRaise(True) self.bt_arrow.setAutoRaise(True)
self.bt_arrow.setArrowType(UpArrow) self.bt_arrow.setArrowType(compat.UpArrow)
self.bt_arrow.setObjectName('bt_arrow') self.bt_arrow.setObjectName('bt_arrow')
self.horizontalLayout.addWidget(self.bt_arrow) self.horizontalLayout.addWidget(self.bt_arrow)
self.line_2 = QtWidgets.QFrame(self.centralwidget) self.line_2 = QtWidgets.QFrame(self.centralwidget)
self.line_2.setFrameShape(VLine) self.line_2.setFrameShape(compat.VLine)
self.line_2.setFrameShadow(Sunken) self.line_2.setFrameShadow(compat.Sunken)
self.line_2.setObjectName('line_2') self.line_2.setObjectName('line_2')
self.horizontalLayout.addWidget(self.line_2) self.horizontalLayout.addWidget(self.line_2)
self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget) self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
@ -422,7 +310,7 @@ class Ui:
self.doubleSpinBox.setObjectName('doubleSpinBox') self.doubleSpinBox.setObjectName('doubleSpinBox')
self.horizontalLayout.addWidget(self.doubleSpinBox) self.horizontalLayout.addWidget(self.doubleSpinBox)
self.toolButton = QtWidgets.QToolButton(self.centralwidget) self.toolButton = QtWidgets.QToolButton(self.centralwidget)
self.toolButton.setPopupMode(InstantPopup) self.toolButton.setPopupMode(compat.InstantPopup)
self.toolButton.setObjectName('toolButton') self.toolButton.setObjectName('toolButton')
self.horizontalLayout.addWidget(self.toolButton) self.horizontalLayout.addWidget(self.toolButton)
self.verticalLayout_5.addLayout(self.horizontalLayout) self.verticalLayout_5.addLayout(self.horizontalLayout)
@ -453,15 +341,15 @@ class Ui:
self.comboBox.addItem('') self.comboBox.addItem('')
self.verticalLayout.addWidget(self.comboBox) self.verticalLayout.addWidget(self.comboBox)
self.horizontalSlider = QtWidgets.QSlider(self.dockWidgetContents) self.horizontalSlider = QtWidgets.QSlider(self.dockWidgetContents)
self.horizontalSlider.setOrientation(Horizontal) self.horizontalSlider.setOrientation(compat.Horizontal)
self.horizontalSlider.setObjectName('horizontalSlider') self.horizontalSlider.setObjectName('horizontalSlider')
self.verticalLayout.addWidget(self.horizontalSlider) self.verticalLayout.addWidget(self.horizontalSlider)
self.textEdit = QtWidgets.QTextEdit(self.dockWidgetContents) self.textEdit = QtWidgets.QTextEdit(self.dockWidgetContents)
self.textEdit.setObjectName('textEdit') self.textEdit.setObjectName('textEdit')
self.verticalLayout.addWidget(self.textEdit) self.verticalLayout.addWidget(self.textEdit)
self.line = QtWidgets.QFrame(self.dockWidgetContents) self.line = QtWidgets.QFrame(self.dockWidgetContents)
self.line.setFrameShape(HLine) self.line.setFrameShape(compat.HLine)
self.line.setFrameShadow(Sunken) self.line.setFrameShadow(compat.Sunken)
self.line.setObjectName('line') self.line.setObjectName('line')
self.verticalLayout.addWidget(self.line) self.verticalLayout.addWidget(self.line)
self.progressBar = QtWidgets.QProgressBar(self.dockWidgetContents) self.progressBar = QtWidgets.QProgressBar(self.dockWidgetContents)
@ -471,8 +359,8 @@ class Ui:
self.verticalLayout_2.addLayout(self.verticalLayout) self.verticalLayout_2.addLayout(self.verticalLayout)
self.frame = QtWidgets.QFrame(self.dockWidgetContents) self.frame = QtWidgets.QFrame(self.dockWidgetContents)
self.frame.setMinimumSize(QtCore.QSize(0, 100)) self.frame.setMinimumSize(QtCore.QSize(0, 100))
self.frame.setFrameShape(StyledPanel) self.frame.setFrameShape(compat.StyledPanel)
self.frame.setFrameShadow(Raised) self.frame.setFrameShadow(compat.Raised)
self.frame.setLineWidth(3) self.frame.setLineWidth(3)
self.frame.setObjectName('frame') self.frame.setObjectName('frame')
self.verticalLayout_2.addWidget(self.frame) self.verticalLayout_2.addWidget(self.frame)
@ -480,7 +368,7 @@ class Ui:
MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(1), self.dockWidget1) MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(1), self.dockWidget1)
self.toolBar = QtWidgets.QToolBar(MainWindow) self.toolBar = QtWidgets.QToolBar(MainWindow)
self.toolBar.setObjectName('toolBar') self.toolBar.setObjectName('toolBar')
MainWindow.addToolBar(TopToolBarArea, self.toolBar) MainWindow.addToolBar(compat.TopToolBarArea, self.toolBar)
self.dockWidget2 = QtWidgets.QDockWidget(MainWindow) self.dockWidget2 = QtWidgets.QDockWidget(MainWindow)
self.dockWidget2.setObjectName('dockWidget2') self.dockWidget2.setObjectName('dockWidget2')
self.dockWidgetContents_2 = QtWidgets.QWidget() self.dockWidgetContents_2 = QtWidgets.QWidget()
@ -488,16 +376,16 @@ class Ui:
self.gridLayout_3 = QtWidgets.QGridLayout(self.dockWidgetContents_2) self.gridLayout_3 = QtWidgets.QGridLayout(self.dockWidgetContents_2)
self.gridLayout_3.setObjectName('gridLayout_3') self.gridLayout_3.setObjectName('gridLayout_3')
self.verticalSlider = QtWidgets.QSlider(self.dockWidgetContents_2) self.verticalSlider = QtWidgets.QSlider(self.dockWidgetContents_2)
self.verticalSlider.setOrientation(Vertical) self.verticalSlider.setOrientation(compat.Vertical)
self.verticalSlider.setObjectName('verticalSlider') self.verticalSlider.setObjectName('verticalSlider')
self.gridLayout_3.addWidget(self.verticalSlider, 0, 0, 1, 1) self.gridLayout_3.addWidget(self.verticalSlider, 0, 0, 1, 1)
self.dockWidget2.setWidget(self.dockWidgetContents_2) self.dockWidget2.setWidget(self.dockWidgetContents_2)
MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(1), self.dockWidget2) MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(1), self.dockWidget2)
self.actionAction = QAction(MainWindow) self.actionAction = compat.QAction(MainWindow)
self.actionAction.setObjectName('actionAction') self.actionAction.setObjectName('actionAction')
self.actionSub_menu = QAction(MainWindow) self.actionSub_menu = compat.QAction(MainWindow)
self.actionSub_menu.setObjectName('actionSub_menu') self.actionSub_menu.setObjectName('actionSub_menu')
self.actionAction_C = QAction(MainWindow) self.actionAction_C = compat.QAction(MainWindow)
self.actionAction_C.setObjectName('actionAction_C') self.actionAction_C.setObjectName('actionAction_C')
self.menuSubmenu_2.addAction(self.actionSub_menu) self.menuSubmenu_2.addAction(self.actionSub_menu)
self.menuSubmenu_2.addAction(self.actionAction_C) self.menuSubmenu_2.addAction(self.actionAction_C)
@ -624,25 +512,7 @@ class Ui:
def main(): def main():
'Application entry point' 'Application entry point'
if args.scale != 1: app, window = shared.setup_app(args, unknown, compat)
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 ui # setup ui
ui = Ui() ui = Ui()
@ -668,19 +538,7 @@ def main():
# tabify dock widgets to show bug #6 # tabify dock widgets to show bug #6
window.tabifyDockWidget(ui.dockWidget1, ui.dockWidget2) window.tabifyDockWidget(ui.dockWidget1, ui.dockWidget2)
# setup stylesheet return shared.exec_app(args, app, window, compat)
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_()
if __name__ == '__main__': if __name__ == '__main__':