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.

236 lines
7.6 KiB

# coding:utf-8
from typing import Union
from PySide6.QtGui import QIcon
from PySide6.QtCore import (QEvent, Qt, QPropertyAnimation, Property, QEasingCurve,
QParallelAnimationGroup, QRect, QSize, QPoint, QRectF)
from PySide6.QtGui import QColor, QPixmap, QPainter
from PySide6.QtWidgets import QFrame, QWidget, QAbstractButton, QApplication
from ...common.config import isDarkTheme
from ...common.icon import FluentIcon as FIF
from ...common.style_sheet import FluentStyleSheet
from .setting_card import SettingCard
from ..layout.v_box_layout import VBoxLayout
class ExpandButton(QAbstractButton):
""" Expand button """
def __init__(self, parent=None):
super().__init__(parent)
self.setFixedSize(30, 30)
self.__angle = 0
self.isHover = False
self.isPressed = False
self.rotateAni = QPropertyAnimation(self, b'angle', self)
self.clicked.connect(self.__onClicked)
def paintEvent(self, e):
painter = QPainter(self)
painter.setRenderHints(QPainter.Antialiasing |
QPainter.SmoothPixmapTransform)
painter.setPen(Qt.NoPen)
# draw background
r = 255 if isDarkTheme() else 0
if self.isPressed:
color = QColor(r, r, r, 10)
elif self.isHover:
color = QColor(r, r, r, 14)
else:
color = Qt.transparent
painter.setBrush(color)
painter.drawRoundedRect(self.rect(), 4, 4)
# draw icon
painter.translate(self.width()//2, self.height()//2)
painter.rotate(self.__angle)
FIF.ARROW_DOWN.render(painter, QRectF(-5, -5, 9.6, 9.6))
def enterEvent(self, e):
self.setHover(True)
def leaveEvent(self, e):
self.setHover(False)
def mousePressEvent(self, e):
super().mousePressEvent(e)
self.setPressed(True)
def mouseReleaseEvent(self, e):
super().mouseReleaseEvent(e)
self.setPressed(False)
def setHover(self, isHover: bool):
self.isHover = isHover
self.update()
def setPressed(self, isPressed: bool):
self.isPressed = isPressed
self.update()
def __onClicked(self):
self.rotateAni.setEndValue(180 if self.angle < 180 else 0)
self.rotateAni.setDuration(200)
self.rotateAni.start()
def getAngle(self):
return self.__angle
def setAngle(self, angle):
self.__angle = angle
self.update()
angle = Property(float, getAngle, setAngle)
class ExpandSettingCard(QFrame):
""" Expandable setting card """
def __init__(self, icon: Union[str, QIcon, FIF], title: str, content: str = None, parent=None):
super().__init__(parent=parent)
self.isExpand = False
self.expandButton = ExpandButton(self)
self.view = QFrame(self)
self.card = SettingCard(icon, title, content, self)
self.viewLayout = VBoxLayout(self.view)
# expand animation
self.aniGroup = QParallelAnimationGroup(self)
self.slideAni = QPropertyAnimation(self.view, b'pos', self)
self.expandAni = QPropertyAnimation(self, b'geometry', self)
self.__initWidget()
def __initWidget(self):
""" initialize widgets """
self.setMinimumHeight(self.card.height())
self.view.hide()
# initialize expand animation
self.aniGroup.addAnimation(self.expandAni)
self.aniGroup.addAnimation(self.slideAni)
self.slideAni.setEasingCurve(QEasingCurve.OutQuad)
self.expandAni.setEasingCurve(QEasingCurve.OutQuad)
self.slideAni.setDuration(200)
self.expandAni.setDuration(200)
# initialize style sheet
self.view.setObjectName('view')
self.setProperty('isExpand', False)
FluentStyleSheet.EXPAND_SETTING_CARD.apply(self.card)
FluentStyleSheet.EXPAND_SETTING_CARD.apply(self)
self.card.installEventFilter(self)
self.aniGroup.finished.connect(self.__onAniFinished)
self.expandButton.clicked.connect(self.toggleExpand)
def addWidget(self, widget: QWidget):
""" add widget to tail """
self.card.hBoxLayout.addWidget(widget, 0, Qt.AlignRight)
self.card.hBoxLayout.addSpacing(19)
self.card.hBoxLayout.addWidget(self.expandButton, 0, Qt.AlignRight)
self.card.hBoxLayout.addSpacing(8)
def setExpand(self, isExpand: bool):
""" set the expand status of card """
if self.isExpand == isExpand:
return
# update style sheet
self.isExpand = isExpand
self.setProperty('isExpand', isExpand)
self.setStyle(QApplication.style())
# start expand animation
ch, vh = self.card.height(), self.view.height()
if isExpand:
self.expandAni.setStartValue(self.geometry())
self.expandAni.setEndValue(
QRect(self.pos(), QSize(self.width(), ch+vh)))
self.slideAni.setStartValue(QPoint(0, ch - vh))
self.slideAni.setEndValue(QPoint(0, ch))
self.view.show()
else:
self.expandAni.setStartValue(self.geometry())
self.expandAni.setEndValue(QRect(self.pos(), self.card.size()))
self.slideAni.setStartValue(QPoint(0, ch))
self.slideAni.setEndValue(QPoint(0, ch - vh))
self.aniGroup.start()
def toggleExpand(self):
""" toggle expand status """
self.setExpand(not self.isExpand)
def resizeEvent(self, e):
self.card.resize(self.width(), self.card.height())
self.view.resize(self.width(), self.view.height())
def eventFilter(self, obj, e):
if obj is self.card:
if e.type() == QEvent.Enter:
self.expandButton.setHover(True)
elif e.type()==QEvent.Leave:
self.expandButton.setHover(False)
elif e.type() == QEvent.MouseButtonPress and e.button() == Qt.LeftButton:
self.expandButton.setPressed(True)
elif e.type() == QEvent.MouseButtonRelease and e.button() == Qt.LeftButton:
self.expandButton.setPressed(False)
self.expandButton.click()
return super().eventFilter(obj, e)
def __onAniFinished(self):
""" expand animation finished slot """
if not self.isExpand:
self.view.hide()
def _adjustViewSize(self):
""" adjust view size """
h = sum(i.height() for i in self.viewLayout.widgets)
spacing = (len(self.viewLayout.widgets) - 1) * \
self.viewLayout.spacing()
margin = self.viewLayout.contentsMargins()
h = h + margin.top() + margin.bottom() + spacing
self.view.resize(self.view.width(), h)
if self.view.isVisible():
self.resize(self.width(), h + self.card.height())
def setValue(self, value):
""" set the value of config item """
pass
class GroupSeparator(QWidget):
""" group separator """
def __init__(self, parent=None):
super().__init__(parent=parent)
self.setFixedHeight(3)
def paintEvent(self, e):
painter = QPainter(self)
c = 35 if isDarkTheme() else 230
painter.setPen(QColor(c, c, c))
painter.drawLine(0, 1, self.width(), 1)
class ExpandGroupSettingCard(ExpandSettingCard):
""" Expand group setting card """
def addGroupWidget(self, widget: QWidget):
""" add widget to group """
if widget in self.viewLayout.widgets:
return
# add separator
if self.viewLayout.count() >= 1:
self.viewLayout.addWidget(GroupSeparator(self.view))
widget.setParent(self.view)
self.viewLayout.addWidget(widget)