You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

414 lines
12 KiB

# coding:utf-8
from typing import Union
from PySide6.QtCore import Qt, Signal
from PySide6.QtGui import QColor, QIcon, QPainter
from PySide6.QtWidgets import QFrame, QHBoxLayout, QLabel, QToolButton, QVBoxLayout, QPushButton
from PySide6.QtSvgWidgets import QSvgWidget
from ..dialog_box.color_dialog import ColorDialog
from ..widgets.combo_box import ComboBox
from ..widgets.switch_button import SwitchButton, IndicatorPosition
from ..widgets.slider import Slider
from ..widgets.icon_widget import IconWidget
from ..widgets.button import HyperlinkButton
from ...common.style_sheet import FluentStyleSheet
from ...common.config import qconfig, isDarkTheme, ConfigItem, OptionsConfigItem
from ...common.icon import FluentIconBase
class SettingCard(QFrame):
""" Setting card """
def __init__(self, icon: Union[str, QIcon, FluentIconBase], title, content=None, parent=None):
"""
Parameters
----------
icon: str | QIcon | FluentIconBase
the icon to be drawn
title: str
the title of card
content: str
the content of card
parent: QWidget
parent widget
"""
super().__init__(parent=parent)
self.iconLabel = IconWidget(icon, self)
self.titleLabel = QLabel(title, self)
self.contentLabel = QLabel(content or '', self)
self.hBoxLayout = QHBoxLayout(self)
self.vBoxLayout = QVBoxLayout()
if not content:
self.contentLabel.hide()
self.setFixedHeight(70 if content else 50)
self.iconLabel.setFixedSize(16, 16)
# initialize layout
self.hBoxLayout.setSpacing(0)
self.hBoxLayout.setContentsMargins(16, 0, 0, 0)
self.hBoxLayout.setAlignment(Qt.AlignVCenter)
self.vBoxLayout.setSpacing(0)
self.vBoxLayout.setContentsMargins(0, 0, 0, 0)
self.vBoxLayout.setAlignment(Qt.AlignVCenter)
self.hBoxLayout.addWidget(self.iconLabel, 0, Qt.AlignLeft)
self.hBoxLayout.addSpacing(16)
self.hBoxLayout.addLayout(self.vBoxLayout)
self.vBoxLayout.addWidget(self.titleLabel, 0, Qt.AlignLeft)
self.vBoxLayout.addWidget(self.contentLabel, 0, Qt.AlignLeft)
self.hBoxLayout.addSpacing(16)
self.hBoxLayout.addStretch(1)
self.contentLabel.setObjectName('contentLabel')
FluentStyleSheet.SETTING_CARD.apply(self)
def setTitle(self, title: str):
""" set the title of card """
self.titleLabel.setText(title)
def setContent(self, content: str):
""" set the content of card """
self.contentLabel.setText(content)
self.contentLabel.setVisible(bool(content))
def setValue(self, value):
""" set the value of config item """
pass
class SwitchSettingCard(SettingCard):
""" Setting card with switch button """
checkedChanged = Signal(bool)
def __init__(self, icon: Union[str, QIcon, FluentIconBase], title, content=None,
configItem: ConfigItem = None, parent=None):
"""
Parameters
----------
icon: str | QIcon | FluentIconBase
the icon to be drawn
title: str
the title of card
content: str
the content of card
configItem: ConfigItem
configuration item operated by the card
parent: QWidget
parent widget
"""
super().__init__(icon, title, content, parent)
self.configItem = configItem
self.switchButton = SwitchButton(
self.tr('Off'), self, IndicatorPosition.RIGHT)
if configItem:
self.setValue(qconfig.get(configItem))
configItem.valueChanged.connect(self.setValue)
# add switch button to layout
self.hBoxLayout.addWidget(self.switchButton, 0, Qt.AlignRight)
self.hBoxLayout.addSpacing(16)
self.switchButton.checkedChanged.connect(self.__onCheckedChanged)
def __onCheckedChanged(self, isChecked: bool):
""" switch button checked state changed slot """
self.setValue(isChecked)
self.checkedChanged.emit(isChecked)
def setValue(self, isChecked: bool):
if self.configItem:
qconfig.set(self.configItem, isChecked)
self.switchButton.setChecked(isChecked)
self.switchButton.setText(
self.tr('On') if isChecked else self.tr('Off'))
def isChecked(self):
return self.switchButton.isChecked()
class RangeSettingCard(SettingCard):
""" Setting card with a slider """
valueChanged = Signal(int)
def __init__(self, configItem, icon: Union[str, QIcon, FluentIconBase], title, content=None, parent=None):
"""
Parameters
----------
configItem: RangeConfigItem
configuration item operated by the card
icon: str | QIcon | FluentIconBase
the icon to be drawn
title: str
the title of card
content: str
the content of card
parent: QWidget
parent widget
"""
super().__init__(icon, title, content, parent)
self.configItem = configItem
self.slider = Slider(Qt.Horizontal, self)
self.valueLabel = QLabel(self)
self.slider.setMinimumWidth(268)
self.slider.setSingleStep(1)
self.slider.setRange(*configItem.range)
self.slider.setValue(configItem.value)
self.valueLabel.setNum(configItem.value)
self.hBoxLayout.addStretch(1)
self.hBoxLayout.addWidget(self.valueLabel, 0, Qt.AlignRight)
self.hBoxLayout.addSpacing(6)
self.hBoxLayout.addWidget(self.slider, 0, Qt.AlignRight)
self.hBoxLayout.addSpacing(16)
self.valueLabel.setObjectName('valueLabel')
configItem.valueChanged.connect(self.setValue)
self.slider.valueChanged.connect(self.__onValueChanged)
def __onValueChanged(self, value: int):
""" slider value changed slot """
self.setValue(value)
self.valueChanged.emit(value)
def setValue(self, value):
qconfig.set(self.configItem, value)
self.valueLabel.setNum(value)
self.valueLabel.adjustSize()
class PushSettingCard(SettingCard):
""" Setting card with a push button """
clicked = Signal()
def __init__(self, text, icon: Union[str, QIcon, FluentIconBase], title, content=None, parent=None):
"""
Parameters
----------
text: str
the text of push button
icon: str | QIcon | FluentIconBase
the icon to be drawn
title: str
the title of card
content: str
the content of card
parent: QWidget
parent widget
"""
super().__init__(icon, title, content, parent)
self.button = QPushButton(text, self)
self.hBoxLayout.addWidget(self.button, 0, Qt.AlignRight)
self.hBoxLayout.addSpacing(16)
self.button.clicked.connect(self.clicked)
class PrimaryPushSettingCard(PushSettingCard):
""" Push setting card with primary color """
def __init__(self, text, icon, title, content=None, parent=None):
super().__init__(text, icon, title, content, parent)
self.button.setObjectName('primaryButton')
class HyperlinkCard(SettingCard):
""" Hyperlink card """
def __init__(self, url, text, icon: Union[str, QIcon, FluentIconBase], title, content=None, parent=None):
"""
Parameters
----------
url: str
the url to be opened
text: str
text of url
icon: str | QIcon | FluentIconBase
the icon to be drawn
title: str
the title of card
content: str
the content of card
text: str
the text of push button
parent: QWidget
parent widget
"""
super().__init__(icon, title, content, parent)
self.linkButton = HyperlinkButton(url, text, self)
self.hBoxLayout.addWidget(self.linkButton, 0, Qt.AlignRight)
self.hBoxLayout.addSpacing(16)
class ColorPickerButton(QToolButton):
""" Color picker button """
colorChanged = Signal(QColor)
def __init__(self, color: QColor, title: str, parent=None, enableAlpha=False):
super().__init__(parent=parent)
self.title = title
self.enableAlpha = enableAlpha
self.setFixedSize(96, 32)
self.setAttribute(Qt.WA_TranslucentBackground)
self.setColor(color)
self.setCursor(Qt.PointingHandCursor)
self.clicked.connect(self.__showColorDialog)
def __showColorDialog(self):
""" show color dialog """
w = ColorDialog(self.color, self.tr(
'Choose ')+self.title, self.window(), self.enableAlpha)
w.colorChanged.connect(self.__onColorChanged)
w.exec()
def __onColorChanged(self, color):
""" color changed slot """
self.setColor(color)
self.colorChanged.emit(color)
def setColor(self, color):
""" set color """
self.color = QColor(color)
self.update()
def paintEvent(self, e):
painter = QPainter(self)
painter.setRenderHints(QPainter.Antialiasing)
pc = QColor(255, 255, 255, 10) if isDarkTheme() else QColor(234, 234, 234)
painter.setPen(pc)
color = QColor(self.color)
if not self.enableAlpha:
color.setAlpha(255)
painter.setBrush(color)
painter.drawRoundedRect(self.rect().adjusted(1, 1, -1, -1), 5, 5)
class ColorSettingCard(SettingCard):
""" Setting card with color picker """
colorChanged = Signal(QColor)
def __init__(self, configItem, icon: Union[str, QIcon, FluentIconBase],
title: str, content: str = None, parent=None, enableAlpha=False):
"""
Parameters
----------
configItem: RangeConfigItem
configuration item operated by the card
icon: str | QIcon | FluentIconBase
the icon to be drawn
title: str
the title of card
content: str
the content of card
parent: QWidget
parent widget
enableAlpha: bool
whether to enable the alpha channel
"""
super().__init__(icon, title, content, parent)
self.configItem = configItem
self.colorPicker = ColorPickerButton(
qconfig.get(configItem), title, self, enableAlpha)
self.hBoxLayout.addWidget(self.colorPicker, 0, Qt.AlignRight)
self.hBoxLayout.addSpacing(16)
self.colorPicker.colorChanged.connect(self.__onColorChanged)
configItem.valueChanged.connect(self.setValue)
def __onColorChanged(self, color: QColor):
qconfig.set(self.configItem, color)
self.colorChanged.emit(color)
def setValue(self, color: QColor):
self.colorPicker.setColor(color)
qconfig.set(self.configItem, color)
class ComboBoxSettingCard(SettingCard):
""" Setting card with a combo box """
def __init__(self, configItem: OptionsConfigItem, icon: Union[str, QIcon, FluentIconBase], title, content=None, texts=None, parent=None):
"""
Parameters
----------
configItem: OptionsConfigItem
configuration item operated by the card
icon: str | QIcon | FluentIconBase
the icon to be drawn
title: str
the title of card
content: str
the content of card
texts: List[str]
the text of items
parent: QWidget
parent widget
"""
super().__init__(icon, title, content, parent)
self.configItem = configItem
self.comboBox = ComboBox(self)
self.hBoxLayout.addWidget(self.comboBox, 0, Qt.AlignRight)
self.hBoxLayout.addSpacing(16)
self.optionToText = {o: t for o, t in zip(configItem.options, texts)}
for text, option in zip(texts, configItem.options):
self.comboBox.addItem(text, userData=option)
self.comboBox.setCurrentText(self.optionToText[qconfig.get(configItem)])
self.comboBox.currentIndexChanged.connect(self._onCurrentIndexChanged)
configItem.valueChanged.connect(self.setValue)
def _onCurrentIndexChanged(self, index: int):
qconfig.set(self.configItem, self.comboBox.itemData(index))
def setValue(self, value):
if value not in self.optionToText:
return
self.comboBox.setCurrentText(self.optionToText[value])
qconfig.set(self.configItem, value)