174 lines
5.1 KiB
Python
174 lines
5.1 KiB
Python
# coding:utf-8
|
|
from typing import Union
|
|
from PySide6.QtCore import Qt, Signal, QRectF
|
|
from PySide6.QtGui import QPainter, QIcon, QColor
|
|
from PySide6.QtWidgets import QApplication, QWidget
|
|
|
|
from ...common.font import setFont
|
|
from ...common.icon import FluentIconBase, drawIcon, Theme
|
|
from ...common.color import autoFallbackThemeColor
|
|
from ...common.style_sheet import themeColor, FluentStyleSheet, isDarkTheme
|
|
from ..widgets.button import PushButton, ToolButton, TransparentToolButton
|
|
from .pivot import Pivot, PivotItem
|
|
|
|
|
|
class SegmentedItem(PivotItem):
|
|
""" Segmented item """
|
|
|
|
def _postInit(self):
|
|
super()._postInit()
|
|
setFont(self, 14)
|
|
|
|
|
|
class SegmentedToolItem(ToolButton):
|
|
""" Pivot item """
|
|
|
|
itemClicked = Signal(bool)
|
|
|
|
def _postInit(self):
|
|
self.isSelected = False
|
|
self.setProperty('isSelected', False)
|
|
self.clicked.connect(lambda: self.itemClicked.emit(True))
|
|
|
|
self.setFixedSize(38, 33)
|
|
FluentStyleSheet.PIVOT.apply(self)
|
|
|
|
def setSelected(self, isSelected: bool):
|
|
if self.isSelected == isSelected:
|
|
return
|
|
|
|
self.isSelected = isSelected
|
|
self.setProperty('isSelected', isSelected)
|
|
self.setStyle(QApplication.style())
|
|
self.update()
|
|
|
|
|
|
class SegmentedToggleToolItem(TransparentToolButton):
|
|
|
|
itemClicked = Signal(bool)
|
|
|
|
def _postInit(self):
|
|
super()._postInit()
|
|
self.isSelected = False
|
|
|
|
self.setFixedSize(50, 32)
|
|
self.clicked.connect(lambda: self.itemClicked.emit(True))
|
|
|
|
def setSelected(self, isSelected: bool):
|
|
if self.isSelected == isSelected:
|
|
return
|
|
|
|
self.isSelected = isSelected
|
|
self.setChecked(isSelected)
|
|
|
|
def _drawIcon(self, icon, painter: QPainter, rect: QRectF, state=QIcon.State.Off):
|
|
if self.isSelected and isinstance(icon, FluentIconBase):
|
|
theme = Theme.DARK if not isDarkTheme() else Theme.LIGHT
|
|
icon = icon.icon(theme)
|
|
|
|
return drawIcon(icon, painter, rect, state)
|
|
|
|
|
|
class SegmentedWidget(Pivot):
|
|
""" Segmented widget """
|
|
|
|
def __init__(self, parent=None):
|
|
super().__init__(parent)
|
|
self.setAttribute(Qt.WA_StyledBackground)
|
|
|
|
def insertItem(self, index: int, routeKey: str, text: str, onClick=None, icon=None):
|
|
if routeKey in self.items:
|
|
return
|
|
|
|
item = SegmentedItem(text, self)
|
|
if icon:
|
|
item.setIcon(icon)
|
|
|
|
self.insertWidget(index, routeKey, item, onClick)
|
|
return item
|
|
|
|
def paintEvent(self, e):
|
|
QWidget.paintEvent(self, e)
|
|
|
|
if not self.currentItem():
|
|
return
|
|
|
|
painter = QPainter(self)
|
|
painter.setRenderHints(QPainter.Antialiasing)
|
|
|
|
# draw background
|
|
if isDarkTheme():
|
|
painter.setPen(QColor(255, 255, 255, 14))
|
|
painter.setBrush(QColor(255, 255, 255, 15))
|
|
else:
|
|
painter.setPen(QColor(0, 0, 0, 19))
|
|
painter.setBrush(QColor(255, 255, 255, 179))
|
|
|
|
item = self.currentItem()
|
|
rect = item.rect().adjusted(1, 1, -1, -1).translated(int(self.slideAni.value()), 0)
|
|
painter.drawRoundedRect(rect, 5, 5)
|
|
|
|
# draw indicator
|
|
painter.setPen(Qt.PenStyle.NoPen)
|
|
painter.setBrush(autoFallbackThemeColor(self.lightIndicatorColor, self.darkIndicatorColor))
|
|
|
|
x = int(self.currentItem().width() / 2 - 8 + self.slideAni.value())
|
|
painter.drawRoundedRect(QRectF(x, self.height() - 3.5, 16, 3), 1.5, 1.5)
|
|
|
|
|
|
class SegmentedToolWidget(SegmentedWidget):
|
|
""" Segmented tool widget """
|
|
|
|
def __init__(self, parent=None):
|
|
super().__init__(parent)
|
|
self.setAttribute(Qt.WA_StyledBackground)
|
|
|
|
def addItem(self, routeKey: str, icon: Union[str, QIcon, FluentIconBase], onClick=None):
|
|
""" add item
|
|
|
|
Parameters
|
|
----------
|
|
routeKey: str
|
|
the unique name of item
|
|
|
|
icon: str | QIcon | FluentIconBase
|
|
the icon of navigation item
|
|
|
|
onClick: callable
|
|
the slot connected to item clicked signal
|
|
"""
|
|
return self.insertItem(-1, routeKey, icon, onClick)
|
|
|
|
def insertItem(self, index: int, routeKey: str, icon: Union[str, QIcon, FluentIconBase], onClick=None):
|
|
if routeKey in self.items:
|
|
return
|
|
|
|
item = self._createItem(icon)
|
|
self.insertWidget(index, routeKey, item, onClick)
|
|
return item
|
|
|
|
def _createItem(self, icon):
|
|
return SegmentedToolItem(icon)
|
|
|
|
|
|
class SegmentedToggleToolWidget(SegmentedToolWidget):
|
|
""" Segmented toggle tool widget """
|
|
|
|
def _createItem(self, icon):
|
|
return SegmentedToggleToolItem(icon)
|
|
|
|
def paintEvent(self, e):
|
|
QWidget.paintEvent(self, e)
|
|
|
|
if not self.currentItem():
|
|
return
|
|
|
|
painter = QPainter(self)
|
|
painter.setRenderHints(QPainter.RenderHint.Antialiasing)
|
|
|
|
painter.setPen(Qt.PenStyle.NoPen)
|
|
painter.setBrush(autoFallbackThemeColor(self.lightIndicatorColor, self.darkIndicatorColor))
|
|
|
|
item = self.currentItem()
|
|
painter.drawRoundedRect(
|
|
QRectF(self.slideAni.value(), 0, item.width(), item.height()), 4, 4) |