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.

189 lines
5.5 KiB

# coding:utf-8
from PySide6.QtCore import QEasingCurve, QPropertyAnimation, Qt, QTimer, Signal, QSize, QPoint, QRectF
from PySide6.QtGui import QPainter
from PySide6.QtWidgets import QLabel, QWidget, QToolButton, QGraphicsOpacityEffect
from PySide6.QtSvgWidgets import QSvgWidget
from ...common import FluentStyleSheet, isDarkTheme, Theme
from ...common.icon import FluentIcon as FIF
class StateCloseButton(QToolButton):
def __init__(self, parent=None):
super().__init__(parent)
self.setFixedSize(12, 12)
self.isPressed = False
self.isEnter = False
def enterEvent(self, e):
self.isEnter = True
self.update()
def leaveEvent(self, e):
self.isEnter = False
self.isPressed = False
self.update()
def mousePressEvent(self, e):
self.isPressed = True
self.update()
super().mousePressEvent(e)
def mouseReleaseEvent(self, e):
self.isPressed = False
self.update()
super().mouseReleaseEvent(e)
def paintEvent(self, e):
painter = QPainter(self)
painter.setRenderHints(QPainter.Antialiasing)
if self.isPressed:
painter.setOpacity(0.6)
elif self.isEnter:
painter.setOpacity(0.8)
theme = Theme.DARK if not isDarkTheme() else Theme.LIGHT
FIF.CLOSE.render(painter, self.rect(), theme)
class StateToolTip(QWidget):
""" State tooltip """
closedSignal = Signal()
def __init__(self, title, content, parent=None):
"""
Parameters
----------
title: str
title of tooltip
content: str
content of tooltip
parant:
parent window
"""
super().__init__(parent)
self.title = title
self.content = content
self.titleLabel = QLabel(self.title, self)
self.contentLabel = QLabel(self.content, self)
self.rotateTimer = QTimer(self)
self.opacityEffect = QGraphicsOpacityEffect(self)
self.animation = QPropertyAnimation(self.opacityEffect, b"opacity")
self.closeButton = StateCloseButton(self)
self.isDone = False
self.rotateAngle = 0
self.deltaAngle = 20
self.__initWidget()
def __initWidget(self):
""" initialize widgets """
self.setAttribute(Qt.WA_StyledBackground)
self.setGraphicsEffect(self.opacityEffect)
self.opacityEffect.setOpacity(1)
self.rotateTimer.setInterval(50)
self.contentLabel.setMinimumWidth(200)
# connect signal to slot
self.closeButton.clicked.connect(self.__onCloseButtonClicked)
self.rotateTimer.timeout.connect(self.__rotateTimerFlowSlot)
self.__setQss()
self.__initLayout()
self.rotateTimer.start()
def __initLayout(self):
""" initialize layout """
self.setFixedSize(max(self.titleLabel.width(),
self.contentLabel.width()) + 56, 51)
self.titleLabel.move(32, 9)
self.contentLabel.move(12, 27)
self.closeButton.move(self.width() - 24, 19)
def __setQss(self):
""" set style sheet """
self.titleLabel.setObjectName("titleLabel")
self.contentLabel.setObjectName("contentLabel")
FluentStyleSheet.STATE_TOOL_TIP.apply(self)
self.titleLabel.adjustSize()
self.contentLabel.adjustSize()
def setTitle(self, title: str):
""" set the title of tooltip """
self.title = title
self.titleLabel.setText(title)
self.titleLabel.adjustSize()
def setContent(self, content: str):
""" set the content of tooltip """
self.content = content
self.contentLabel.setText(content)
# adjustSize() will mask spinner get stuck
self.contentLabel.adjustSize()
def setState(self, isDone=False):
""" set the state of tooltip """
self.isDone = isDone
self.update()
if isDone:
QTimer.singleShot(1000, self.__fadeOut)
def __onCloseButtonClicked(self):
""" close button clicked slot """
self.closedSignal.emit()
self.hide()
def __fadeOut(self):
""" fade out """
self.rotateTimer.stop()
self.animation.setDuration(200)
self.animation.setStartValue(1)
self.animation.setEndValue(0)
self.animation.finished.connect(self.deleteLater)
self.animation.start()
def __rotateTimerFlowSlot(self):
""" rotate timer time out slot """
self.rotateAngle = (self.rotateAngle + self.deltaAngle) % 360
self.update()
def getSuitablePos(self):
""" get suitable position in main window """
for i in range(10):
dy = i*(self.height() + 16)
pos = QPoint(self.parent().width() - self.width() - 24, 50+dy)
widget = self.parent().childAt(pos + QPoint(2, 2))
if isinstance(widget, StateToolTip):
pos += QPoint(0, self.height() + 16)
else:
break
return pos
def paintEvent(self, e):
""" paint state tooltip """
super().paintEvent(e)
painter = QPainter(self)
painter.setRenderHints(QPainter.Antialiasing)
painter.setPen(Qt.NoPen)
theme = Theme.DARK if not isDarkTheme() else Theme.LIGHT
if not self.isDone:
painter.translate(19, 18)
painter.rotate(self.rotateAngle)
FIF.SYNC.render(painter, QRectF(-8, -8, 16, 16), theme)
else:
FIF.COMPLETED.render(painter, QRectF(11, 10, 16, 16), theme)