initial fluent-widgets ui

This commit is contained in:
2025-08-14 18:45:16 +08:00
parent 746e83ab23
commit 4c66886257
1198 changed files with 805339 additions and 0 deletions

View File

@ -0,0 +1,272 @@
# coding:utf-8
from typing import Dict
from PySide6.QtCore import Qt, Signal, QRectF
from PySide6.QtGui import QPainter, QFont, QColor
from PySide6.QtWidgets import QApplication, QPushButton, QWidget, QHBoxLayout, QSizePolicy
from ...common.font import setFont
from ...common.router import qrouter
from ...common.style_sheet import themeColor, FluentStyleSheet
from ...common.color import autoFallbackThemeColor
from ...common.animation import FluentAnimation, FluentAnimationType, FluentAnimationProperty
from ..widgets.button import PushButton
from .navigation_panel import RouteKeyError
class PivotItem(PushButton):
""" Pivot item """
itemClicked = Signal(bool)
def _postInit(self):
self.isSelected = False
self.setProperty('isSelected', False)
self.clicked.connect(lambda: self.itemClicked.emit(True))
self.setAttribute(Qt.WA_LayoutUsesWidgetRect)
FluentStyleSheet.PIVOT.apply(self)
setFont(self, 18)
def setSelected(self, isSelected: bool):
if self.isSelected == isSelected:
return
self.isSelected = isSelected
self.setProperty('isSelected', isSelected)
self.setStyle(QApplication.style())
self.update()
class Pivot(QWidget):
""" Pivot """
currentItemChanged = Signal(str)
def __init__(self, parent=None):
super().__init__(parent)
self.items = {} # type: Dict[str, PivotItem]
self._currentRouteKey = None
self.lightIndicatorColor = QColor()
self.darkIndicatorColor = QColor()
self.hBoxLayout = QHBoxLayout(self)
self.slideAni = FluentAnimation.create(
FluentAnimationType.POINT_TO_POINT, FluentAnimationProperty.SCALE, value=0, parent=self)
FluentStyleSheet.PIVOT.apply(self)
self.hBoxLayout.setSpacing(0)
self.hBoxLayout.setAlignment(Qt.AlignLeft)
self.hBoxLayout.setContentsMargins(0, 0, 0, 0)
self.hBoxLayout.setSizeConstraint(QHBoxLayout.SetMinimumSize)
self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
def addItem(self, routeKey: str, text: str, onClick=None, icon=None):
""" add item
Parameters
----------
routeKey: str
the unique name of item
text: str
the text of navigation item
onClick: callable
the slot connected to item clicked signal
icon: str
the icon of navigation item
"""
return self.insertItem(-1, routeKey, text, onClick, icon)
def addWidget(self, routeKey: str, widget: PivotItem, onClick=None):
""" add widget
Parameters
----------
routeKey: str
the unique name of item
widget: PivotItem
navigation widget
onClick: callable
the slot connected to item clicked signal
"""
self.insertWidget(-1, routeKey, widget, onClick)
def insertItem(self, index: int, routeKey: str, text: str, onClick=None, icon=None):
""" insert item
Parameters
----------
index: int
insert position
routeKey: str
the unique name of item
text: str
the text of navigation item
onClick: callable
the slot connected to item clicked signal
icon: str
the icon of navigation item
"""
if routeKey in self.items:
return
item = PivotItem(text, self)
if icon:
item.setIcon(icon)
self.insertWidget(index, routeKey, item, onClick)
return item
def insertWidget(self, index: int, routeKey: str, widget: PivotItem, onClick=None):
""" insert item
Parameters
----------
index: int
insert position
routeKey: str
the unique name of item
widget: PivotItem
navigation widget
onClick: callable
the slot connected to item clicked signal
"""
if routeKey in self.items:
return
widget.setProperty('routeKey', routeKey)
widget.itemClicked.connect(self._onItemClicked)
if onClick:
widget.itemClicked.connect(onClick)
self.items[routeKey] = widget
self.hBoxLayout.insertWidget(index, widget, 1)
def removeWidget(self, routeKey: str):
""" remove widget
Parameters
----------
routeKey: str
the unique name of item
"""
if routeKey not in self.items:
return
item = self.items.pop(routeKey)
self.hBoxLayout.removeWidget(item)
qrouter.remove(routeKey)
item.deleteLater()
if not self.items:
self._currentRouteKey = None
def clear(self):
""" clear all navigation items """
for k, w in self.items.items():
self.hBoxLayout.removeWidget(w)
qrouter.remove(k)
w.deleteLater()
self.items.clear()
self._currentRouteKey = None
def currentItem(self):
""" Returns the current selected item """
if self._currentRouteKey is None:
return None
return self.widget(self._currentRouteKey)
def currentRouteKey(self):
return self._currentRouteKey
def setCurrentItem(self, routeKey: str):
""" set current selected item
Parameters
----------
routeKey: str
the unique name of item
"""
if routeKey not in self.items or routeKey == self.currentRouteKey():
return
self._currentRouteKey = routeKey
self.slideAni.startAnimation(self.widget(routeKey).x())
for k, item in self.items.items():
item.setSelected(k == routeKey)
self.currentItemChanged.emit(routeKey)
def showEvent(self, e):
super().showEvent(e)
self._adjustIndicatorPos()
def setItemFontSize(self, size: int):
""" set the pixel font size of items """
for item in self.items.values():
font = item.font()
font.setPixelSize(size)
item.setFont(font)
item.adjustSize()
def setItemText(self, routeKey: str, text: str):
""" set the text of item """
item = self.widget(routeKey)
item.setText(text)
def setIndicatorColor(self, light, dark):
self.lightIndicatorColor = QColor(light)
self.darkIndicatorColor = QColor(dark)
self.update()
def _onItemClicked(self):
item = self.sender() # type: PivotItem
self.setCurrentItem(item.property('routeKey'))
def widget(self, routeKey: str):
if routeKey not in self.items:
raise RouteKeyError(f"`{routeKey}` is illegal.")
return self.items[routeKey]
def resizeEvent(self, e) -> None:
super().resizeEvent(e)
self._adjustIndicatorPos()
def _adjustIndicatorPos(self):
item = self.currentItem()
if item:
self.slideAni.stop()
self.slideAni.setValue(item.x())
def paintEvent(self, e):
super().paintEvent(e)
if not self.currentItem():
return
painter = QPainter(self)
painter.setRenderHints(QPainter.Antialiasing)
painter.setPen(Qt.NoPen)
painter.setBrush(autoFallbackThemeColor(self.lightIndicatorColor, self.darkIndicatorColor))
x = int(self.currentItem().width() / 2 - 8 + self.slideAni.value())
painter.drawRoundedRect(x, self.height() - 3, 16, 3, 1.5, 1.5)