704 lines
19 KiB
Python
704 lines
19 KiB
Python
# coding:utf-8
|
|
from enum import Enum
|
|
from typing import Union
|
|
import json
|
|
|
|
from PySide6.QtXml import QDomDocument
|
|
from PySide6.QtCore import QRectF, Qt, QFile, QObject, QRect
|
|
from PySide6.QtGui import QIcon, QIconEngine, QColor, QPixmap, QImage, QPainter, QFontDatabase, QFont, QAction, QPainterPath
|
|
from PySide6.QtSvg import QSvgRenderer
|
|
from PySide6.QtWidgets import QApplication
|
|
|
|
from .config import isDarkTheme, Theme
|
|
from .overload import singledispatchmethod
|
|
|
|
|
|
class FluentIconEngine(QIconEngine):
|
|
""" Fluent icon engine """
|
|
|
|
def __init__(self, icon, reverse=False):
|
|
"""
|
|
Parameters
|
|
----------
|
|
icon: QICon | Icon | FluentIconBase
|
|
the icon to be drawn
|
|
|
|
reverse: bool
|
|
whether to reverse the theme of icon
|
|
"""
|
|
super().__init__()
|
|
self.icon = icon
|
|
self.isThemeReversed = reverse
|
|
|
|
def paint(self, painter, rect, mode, state):
|
|
painter.save()
|
|
|
|
if mode == QIcon.Disabled:
|
|
painter.setOpacity(0.5)
|
|
elif mode == QIcon.Selected:
|
|
painter.setOpacity(0.7)
|
|
|
|
# change icon color according to the theme
|
|
icon = self.icon
|
|
|
|
if not self.isThemeReversed:
|
|
theme = Theme.AUTO
|
|
else:
|
|
theme = Theme.LIGHT if isDarkTheme() else Theme.DARK
|
|
|
|
if isinstance(self.icon, Icon):
|
|
icon = self.icon.fluentIcon.icon(theme)
|
|
elif isinstance(self.icon, FluentIconBase):
|
|
icon = self.icon.icon(theme)
|
|
|
|
if rect.x() == 19:
|
|
rect = rect.adjusted(-1, 0, 0, 0)
|
|
|
|
icon.paint(painter, rect, Qt.AlignCenter, QIcon.Normal, state)
|
|
painter.restore()
|
|
|
|
|
|
class SvgIconEngine(QIconEngine):
|
|
""" Svg icon engine """
|
|
|
|
def __init__(self, svg: str):
|
|
super().__init__()
|
|
self.svg = svg
|
|
|
|
def paint(self, painter, rect, mode, state):
|
|
drawSvgIcon(self.svg.encode(), painter, rect)
|
|
|
|
def clone(self) -> QIconEngine:
|
|
return SvgIconEngine(self.svg)
|
|
|
|
def pixmap(self, size, mode, state):
|
|
image = QImage(size, QImage.Format_ARGB32)
|
|
image.fill(Qt.transparent)
|
|
pixmap = QPixmap.fromImage(image, Qt.NoFormatConversion)
|
|
|
|
painter = QPainter(pixmap)
|
|
rect = QRect(0, 0, size.width(), size.height())
|
|
self.paint(painter, rect, mode, state)
|
|
return pixmap
|
|
|
|
|
|
class FontIconEngine(QIconEngine):
|
|
""" Font icon engine """
|
|
|
|
def __init__(self, fontFamily: str, char: str, color, isBold):
|
|
super().__init__()
|
|
self.color = color
|
|
self.char = char
|
|
self.fontFamily = fontFamily
|
|
self.isBold = isBold
|
|
|
|
def paint(self, painter, rect, mode, state):
|
|
font = QFont(self.fontFamily)
|
|
font.setBold(self.isBold)
|
|
font.setPixelSize(round(rect.height()))
|
|
painter.setFont(font)
|
|
painter.setPen(Qt.PenStyle.NoPen)
|
|
painter.setBrush(self.color)
|
|
painter.setRenderHints(
|
|
QPainter.RenderHint.Antialiasing | QPainter.RenderHint.TextAntialiasing)
|
|
|
|
path = QPainterPath()
|
|
path.addText(rect.x(), rect.y() + rect.height(), font, self.char)
|
|
painter.drawPath(path)
|
|
|
|
|
|
def clone(self) -> QIconEngine:
|
|
return FontIconEngine(self.fontFamily, self.char, self.color, self.isBold)
|
|
|
|
def pixmap(self, size, mode, state):
|
|
image = QImage(size, QImage.Format_ARGB32)
|
|
image.fill(Qt.transparent)
|
|
pixmap = QPixmap.fromImage(image, Qt.NoFormatConversion)
|
|
|
|
painter = QPainter(pixmap)
|
|
rect = QRect(0, 0, size.width(), size.height())
|
|
self.paint(painter, rect, mode, state)
|
|
return pixmap
|
|
|
|
|
|
def getIconColor(theme=Theme.AUTO, reverse=False):
|
|
""" get the color of icon based on theme """
|
|
if not reverse:
|
|
lc, dc = "black", "white"
|
|
else:
|
|
lc, dc = "white", "black"
|
|
|
|
if theme == Theme.AUTO:
|
|
color = dc if isDarkTheme() else lc
|
|
else:
|
|
color = dc if theme == Theme.DARK else lc
|
|
|
|
return color
|
|
|
|
|
|
def drawSvgIcon(icon, painter, rect):
|
|
""" draw svg icon
|
|
|
|
Parameters
|
|
----------
|
|
icon: str | bytes | QByteArray
|
|
the path or code of svg icon
|
|
|
|
painter: QPainter
|
|
painter
|
|
|
|
rect: QRect | QRectF
|
|
the rect to render icon
|
|
"""
|
|
renderer = QSvgRenderer(icon)
|
|
renderer.render(painter, QRectF(rect))
|
|
|
|
|
|
def writeSvg(iconPath: str, indexes=None, **attributes):
|
|
""" write svg with specified attributes
|
|
|
|
Parameters
|
|
----------
|
|
iconPath: str
|
|
svg icon path
|
|
|
|
indexes: List[int]
|
|
the path to be filled
|
|
|
|
**attributes:
|
|
the attributes of path
|
|
|
|
Returns
|
|
-------
|
|
svg: str
|
|
svg code
|
|
"""
|
|
if not iconPath.lower().endswith('.svg'):
|
|
return ""
|
|
|
|
f = QFile(iconPath)
|
|
f.open(QFile.ReadOnly)
|
|
|
|
dom = QDomDocument()
|
|
dom.setContent(f.readAll())
|
|
|
|
f.close()
|
|
|
|
# change the color of each path
|
|
pathNodes = dom.elementsByTagName('path')
|
|
indexes = range(pathNodes.length()) if not indexes else indexes
|
|
for i in indexes:
|
|
element = pathNodes.at(i).toElement()
|
|
|
|
for k, v in attributes.items():
|
|
element.setAttribute(k, v)
|
|
|
|
return dom.toString()
|
|
|
|
|
|
def drawIcon(icon, painter, rect, state=QIcon.Off, **attributes):
|
|
""" draw icon
|
|
|
|
Parameters
|
|
----------
|
|
icon: str | QIcon | FluentIconBaseBase
|
|
the icon to be drawn
|
|
|
|
painter: QPainter
|
|
painter
|
|
|
|
rect: QRect | QRectF
|
|
the rect to render icon
|
|
|
|
**attribute:
|
|
the attribute of svg icon
|
|
"""
|
|
if isinstance(icon, FluentIconBase):
|
|
icon.render(painter, rect, **attributes)
|
|
elif isinstance(icon, Icon):
|
|
icon.fluentIcon.render(painter, rect, **attributes)
|
|
else:
|
|
icon = QIcon(icon)
|
|
icon.paint(painter, QRectF(rect).toRect(), Qt.AlignCenter, state=state)
|
|
|
|
|
|
class FluentIconBase:
|
|
""" Fluent icon base class """
|
|
|
|
def path(self, theme=Theme.AUTO) -> str:
|
|
""" get the path of icon
|
|
|
|
Parameters
|
|
----------
|
|
theme: Theme
|
|
the theme of icon
|
|
* `Theme.Light`: black icon
|
|
* `Theme.DARK`: white icon
|
|
* `Theme.AUTO`: icon color depends on `config.theme`
|
|
"""
|
|
raise NotImplementedError
|
|
|
|
def icon(self, theme=Theme.AUTO, color: QColor = None) -> QIcon:
|
|
""" create a fluent icon
|
|
|
|
Parameters
|
|
----------
|
|
theme: Theme
|
|
the theme of icon
|
|
* `Theme.Light`: black icon
|
|
* `Theme.DARK`: white icon
|
|
* `Theme.AUTO`: icon color depends on `qconfig.theme`
|
|
|
|
color: QColor | Qt.GlobalColor | str
|
|
icon color, only applicable to svg icon
|
|
"""
|
|
path = self.path(theme)
|
|
|
|
if not (path.endswith('.svg') and color):
|
|
return QIcon(self.path(theme))
|
|
|
|
color = QColor(color).name()
|
|
return QIcon(SvgIconEngine(writeSvg(path, fill=color)))
|
|
|
|
def colored(self, lightColor: QColor, darkColor: QColor) -> "ColoredFluentIcon":
|
|
""" create a colored fluent icon
|
|
|
|
Parameters
|
|
----------
|
|
lightColor: str | QColor | Qt.GlobalColor
|
|
icon color in light mode
|
|
|
|
darkColor: str | QColor | Qt.GlobalColor
|
|
icon color in dark mode
|
|
"""
|
|
return ColoredFluentIcon(self, lightColor, darkColor)
|
|
|
|
def qicon(self, reverse=False) -> QIcon:
|
|
""" convert to QIcon, the theme of icon will be updated synchronously with app
|
|
|
|
Parameters
|
|
----------
|
|
reverse: bool
|
|
whether to reverse the theme of icon
|
|
"""
|
|
return QIcon(FluentIconEngine(self, reverse))
|
|
|
|
def render(self, painter, rect, theme=Theme.AUTO, indexes=None, **attributes):
|
|
""" draw svg icon
|
|
|
|
Parameters
|
|
----------
|
|
painter: QPainter
|
|
painter
|
|
|
|
rect: QRect | QRectF
|
|
the rect to render icon
|
|
|
|
theme: Theme
|
|
the theme of icon
|
|
* `Theme.Light`: black icon
|
|
* `Theme.DARK`: white icon
|
|
* `Theme.AUTO`: icon color depends on `config.theme`
|
|
|
|
indexes: List[int]
|
|
the svg path to be modified
|
|
|
|
**attributes:
|
|
the attributes of modified path
|
|
"""
|
|
icon = self.path(theme)
|
|
|
|
if icon.endswith('.svg'):
|
|
if attributes:
|
|
icon = writeSvg(icon, indexes, **attributes).encode()
|
|
|
|
drawSvgIcon(icon, painter, rect)
|
|
else:
|
|
icon = QIcon(icon)
|
|
rect = QRectF(rect).toRect()
|
|
painter.drawPixmap(rect, icon.pixmap(QRectF(rect).toRect().size()))
|
|
|
|
|
|
class FluentFontIconBase(FluentIconBase):
|
|
""" Fluent font icon base class """
|
|
|
|
_isFontLoaded = False
|
|
fontId = None
|
|
fontFamily = None
|
|
_iconNames = {}
|
|
|
|
def __init__(self, char: str):
|
|
super().__init__()
|
|
self.char = char
|
|
self.lightColor = QColor(0, 0, 0)
|
|
self.darkColor = QColor(255, 255, 255)
|
|
self.isBold = False
|
|
self.loadFont()
|
|
|
|
@classmethod
|
|
def fromName(cls, name: str):
|
|
icon = cls("")
|
|
icon.char = cls._iconNames.get(name, "")
|
|
return icon
|
|
|
|
def bold(self):
|
|
self.isBold = True
|
|
return self
|
|
|
|
def icon(self, theme=Theme.AUTO, color: QColor = None) -> QIcon:
|
|
if not color:
|
|
color = self._getIconColor(theme)
|
|
|
|
return QIcon(FontIconEngine(self.fontFamily, self.char, color, self.isBold))
|
|
|
|
def colored(self, lightColor, darkColor):
|
|
self.lightColor = QColor(lightColor)
|
|
self.darkColor = QColor(darkColor)
|
|
return self
|
|
|
|
def render(self, painter: QPainter, rect, theme=Theme.AUTO, indexes=None, **attributes):
|
|
color = self._getIconColor(theme)
|
|
|
|
if "fill" in attributes:
|
|
color = QColor(attributes["fill"])
|
|
|
|
font = QFont(self.fontFamily)
|
|
font.setBold(self.isBold)
|
|
font.setPixelSize(round(rect.height()))
|
|
painter.setFont(font)
|
|
painter.setPen(Qt.PenStyle.NoPen)
|
|
painter.setBrush(color)
|
|
painter.setRenderHints(QPainter.RenderHint.Antialiasing | QPainter.RenderHint.TextAntialiasing)
|
|
|
|
path = QPainterPath()
|
|
path.addText(rect.x(), rect.y() + rect.height(), font, self.char)
|
|
painter.drawPath(path)
|
|
|
|
def iconNameMapPath(self) -> str:
|
|
return None
|
|
|
|
def loadFont(self):
|
|
""" Load icon font """
|
|
cls = self.__class__
|
|
if cls._isFontLoaded or not QApplication.instance():
|
|
return
|
|
|
|
file = QFile(self.path())
|
|
if not file.open(QFile.ReadOnly):
|
|
raise FileNotFoundError(f"Cannot open font file: {self.path()}")
|
|
|
|
data = file.readAll()
|
|
file.close()
|
|
|
|
cls.fontId = QFontDatabase.addApplicationFontFromData(data)
|
|
cls.fontFamily = QFontDatabase.applicationFontFamilies(cls.fontId)[0]
|
|
|
|
if self.iconNameMapPath():
|
|
self.loadIconNames()
|
|
|
|
def loadIconNames(self):
|
|
""" Load icon name map """
|
|
cls = self.__class__
|
|
cls._iconNames.clear()
|
|
|
|
file = QFile(self.iconNameMapPath())
|
|
if not file.open(QFile.ReadOnly):
|
|
raise FileNotFoundError(f"Cannot open font file: {self.iconNameMapPath()}")
|
|
|
|
cls._iconNames = json.loads(str(file.readAll(), encoding='utf-8'))
|
|
file.close()
|
|
|
|
def _getIconColor(self, theme):
|
|
if theme == Theme.AUTO:
|
|
color = self.darkColor if isDarkTheme() else self.lightColor
|
|
else:
|
|
color = self.darkColor if theme == Theme.DARK else self.lightColor
|
|
|
|
return color
|
|
|
|
|
|
class ColoredFluentIcon(FluentIconBase):
|
|
""" Colored fluent icon """
|
|
|
|
def __init__(self, icon: FluentIconBase, lightColor, darkColor):
|
|
"""
|
|
Parameters
|
|
----------
|
|
icon: FluentIconBase
|
|
the icon to be colored
|
|
|
|
lightColor: str | QColor | Qt.GlobalColor
|
|
icon color in light mode
|
|
|
|
darkColor: str | QColor | Qt.GlobalColor
|
|
icon color in dark mode
|
|
"""
|
|
super().__init__()
|
|
self.fluentIcon = icon
|
|
self.lightColor = QColor(lightColor)
|
|
self.darkColor = QColor(darkColor)
|
|
|
|
def path(self, theme=Theme.AUTO) -> str:
|
|
return self.fluentIcon.path(theme)
|
|
|
|
def render(self, painter, rect, theme=Theme.AUTO, indexes=None, **attributes):
|
|
icon = self.path(theme)
|
|
|
|
if not icon.endswith('.svg'):
|
|
return self.fluentIcon.render(painter, rect, theme, indexes, attributes)
|
|
|
|
if theme == Theme.AUTO:
|
|
color = self.darkColor if isDarkTheme() else self.lightColor
|
|
else:
|
|
color = self.darkColor if theme == Theme.DARK else self.lightColor
|
|
|
|
attributes.update(fill=color.name())
|
|
icon = writeSvg(icon, indexes, **attributes).encode()
|
|
drawSvgIcon(icon, painter, rect)
|
|
|
|
|
|
|
|
class FluentIcon(FluentIconBase, Enum):
|
|
""" Fluent icon """
|
|
|
|
UP = "Up"
|
|
ADD = "Add"
|
|
BUS = "Bus"
|
|
CAR = "Car"
|
|
CUT = "Cut"
|
|
IOT = "IOT"
|
|
PIN = "Pin"
|
|
TAG = "Tag"
|
|
VPN = "VPN"
|
|
CAFE = "Cafe"
|
|
CHAT = "Chat"
|
|
COPY = "Copy"
|
|
CODE = "Code"
|
|
DOWN = "Down"
|
|
EDIT = "Edit"
|
|
FLAG = "Flag"
|
|
FONT = "Font"
|
|
GAME = "Game"
|
|
HELP = "Help"
|
|
HIDE = "Hide"
|
|
HOME = "Home"
|
|
INFO = "Info"
|
|
LEAF = "Leaf"
|
|
LINK = "Link"
|
|
MAIL = "Mail"
|
|
MENU = "Menu"
|
|
MUTE = "Mute"
|
|
MORE = "More"
|
|
MOVE = "Move"
|
|
PLAY = "Play"
|
|
SAVE = "Save"
|
|
SEND = "Send"
|
|
SYNC = "Sync"
|
|
UNIT = "Unit"
|
|
VIEW = "View"
|
|
WIFI = "Wifi"
|
|
ZOOM = "Zoom"
|
|
ALBUM = "Album"
|
|
BRUSH = "Brush"
|
|
BROOM = "Broom"
|
|
CLOSE = "Close"
|
|
CLOUD = "Cloud"
|
|
EMBED = "Embed"
|
|
GLOBE = "Globe"
|
|
HEART = "Heart"
|
|
LABEL = "Label"
|
|
MEDIA = "Media"
|
|
MOVIE = "Movie"
|
|
MUSIC = "Music"
|
|
ROBOT = "Robot"
|
|
PAUSE = "Pause"
|
|
PASTE = "Paste"
|
|
PHOTO = "Photo"
|
|
PHONE = "Phone"
|
|
PRINT = "Print"
|
|
SHARE = "Share"
|
|
TILES = "Tiles"
|
|
UNPIN = "Unpin"
|
|
VIDEO = "Video"
|
|
TRAIN = "Train"
|
|
ADD_TO ="AddTo"
|
|
ACCEPT = "Accept"
|
|
CAMERA = "Camera"
|
|
CANCEL = "Cancel"
|
|
DELETE = "Delete"
|
|
FOLDER = "Folder"
|
|
FILTER = "Filter"
|
|
MARKET = "Market"
|
|
SCROLL = "Scroll"
|
|
LAYOUT = "Layout"
|
|
GITHUB = "GitHub"
|
|
UPDATE = "Update"
|
|
REMOVE = "Remove"
|
|
RETURN = "Return"
|
|
PEOPLE = "People"
|
|
QRCODE = "QRCode"
|
|
RINGER = "Ringer"
|
|
ROTATE = "Rotate"
|
|
SEARCH = "Search"
|
|
VOLUME = "Volume"
|
|
FRIGID = "Frigid"
|
|
SAVE_AS = "SaveAs"
|
|
ZOOM_IN = "ZoomIn"
|
|
CONNECT ="Connect"
|
|
HISTORY = "History"
|
|
SETTING = "Setting"
|
|
PALETTE = "Palette"
|
|
MESSAGE = "Message"
|
|
FIT_PAGE = "FitPage"
|
|
ZOOM_OUT = "ZoomOut"
|
|
AIRPLANE = "Airplane"
|
|
ASTERISK = "Asterisk"
|
|
CALORIES = "Calories"
|
|
CALENDAR = "Calendar"
|
|
FEEDBACK = "Feedback"
|
|
LIBRARY = "BookShelf"
|
|
MINIMIZE = "Minimize"
|
|
CHECKBOX = "CheckBox"
|
|
DOCUMENT = "Document"
|
|
LANGUAGE = "Language"
|
|
DOWNLOAD = "Download"
|
|
QUESTION = "Question"
|
|
SPEAKERS = "Speakers"
|
|
DATE_TIME = "DateTime"
|
|
FONT_SIZE = "FontSize"
|
|
HOME_FILL = "HomeFill"
|
|
PAGE_LEFT = "PageLeft"
|
|
SAVE_COPY = "SaveCopy"
|
|
SEND_FILL = "SendFill"
|
|
SKIP_BACK = "SkipBack"
|
|
SPEED_OFF = "SpeedOff"
|
|
ALIGNMENT = "Alignment"
|
|
BLUETOOTH = "Bluetooth"
|
|
COMPLETED = "Completed"
|
|
CONSTRACT = "Constract"
|
|
HEADPHONE = "Headphone"
|
|
MEGAPHONE = "Megaphone"
|
|
PROJECTOR = "Projector"
|
|
EDUCATION = "Education"
|
|
LEFT_ARROW = "LeftArrow"
|
|
ERASE_TOOL = "EraseTool"
|
|
PAGE_RIGHT = "PageRight"
|
|
PLAY_SOLID = "PlaySolid"
|
|
BOOK_SHELF = "BookShelf"
|
|
HIGHTLIGHT = "Highlight"
|
|
FOLDER_ADD = "FolderAdd"
|
|
PAUSE_BOLD = "PauseBold"
|
|
PENCIL_INK = "PencilInk"
|
|
PIE_SINGLE = "PieSingle"
|
|
QUICK_NOTE = "QuickNote"
|
|
SPEED_HIGH = "SpeedHigh"
|
|
STOP_WATCH = "StopWatch"
|
|
ZIP_FOLDER = "ZipFolder"
|
|
BASKETBALL = "Basketball"
|
|
BRIGHTNESS = "Brightness"
|
|
DICTIONARY = "Dictionary"
|
|
MICROPHONE = "Microphone"
|
|
ARROW_DOWN = "ChevronDown"
|
|
FULL_SCREEN = "FullScreen"
|
|
MIX_VOLUMES = "MixVolumes"
|
|
REMOVE_FROM = "RemoveFrom"
|
|
RIGHT_ARROW = "RightArrow"
|
|
QUIET_HOURS ="QuietHours"
|
|
FINGERPRINT = "Fingerprint"
|
|
APPLICATION = "Application"
|
|
CERTIFICATE = "Certificate"
|
|
TRANSPARENT = "Transparent"
|
|
IMAGE_EXPORT = "ImageExport"
|
|
SPEED_MEDIUM = "SpeedMedium"
|
|
LIBRARY_FILL = "LibraryFill"
|
|
MUSIC_FOLDER = "MusicFolder"
|
|
POWER_BUTTON = "PowerButton"
|
|
SKIP_FORWARD = "SkipForward"
|
|
CARE_UP_SOLID = "CareUpSolid"
|
|
ACCEPT_MEDIUM = "AcceptMedium"
|
|
CANCEL_MEDIUM = "CancelMedium"
|
|
CHEVRON_RIGHT = "ChevronRight"
|
|
CLIPPING_TOOL = "ClippingTool"
|
|
SEARCH_MIRROR = "SearchMirror"
|
|
SHOPPING_CART = "ShoppingCart"
|
|
FONT_INCREASE = "FontIncrease"
|
|
BACK_TO_WINDOW = "BackToWindow"
|
|
COMMAND_PROMPT = "CommandPrompt"
|
|
CLOUD_DOWNLOAD = "CloudDownload"
|
|
DICTIONARY_ADD = "DictionaryAdd"
|
|
CARE_DOWN_SOLID = "CareDownSolid"
|
|
CARE_LEFT_SOLID = "CareLeftSolid"
|
|
CLEAR_SELECTION = "ClearSelection"
|
|
DEVELOPER_TOOLS = "DeveloperTools"
|
|
BACKGROUND_FILL = "BackgroundColor"
|
|
CARE_RIGHT_SOLID = "CareRightSolid"
|
|
CHEVRON_DOWN_MED = "ChevronDownMed"
|
|
CHEVRON_RIGHT_MED = "ChevronRightMed"
|
|
EMOJI_TAB_SYMBOLS = "EmojiTabSymbols"
|
|
EXPRESSIVE_INPUT_ENTRY = "ExpressiveInputEntry"
|
|
|
|
def path(self, theme=Theme.AUTO):
|
|
return f':/qfluentwidgets/images/icons/{self.value}_{getIconColor(theme)}.svg'
|
|
|
|
|
|
class Icon(QIcon):
|
|
|
|
def __init__(self, fluentIcon: FluentIcon):
|
|
super().__init__(fluentIcon.path())
|
|
self.fluentIcon = fluentIcon
|
|
|
|
|
|
def toQIcon(icon: Union[QIcon, FluentIconBase, str]) -> QIcon:
|
|
""" convet `icon` to `QIcon` """
|
|
if isinstance(icon, str):
|
|
return QIcon(icon)
|
|
|
|
if isinstance(icon, FluentIconBase):
|
|
return icon.icon()
|
|
|
|
return icon
|
|
|
|
|
|
class Action(QAction):
|
|
""" Fluent action
|
|
|
|
Constructors
|
|
------------
|
|
* Action(`parent`: QWidget = None, `**kwargs`)
|
|
* Action(`text`: str, `parent`: QWidget = None, `**kwargs`)
|
|
* Action(`icon`: QIcon | FluentIconBase, `parent`: QWidget = None, `**kwargs`)
|
|
"""
|
|
|
|
@singledispatchmethod
|
|
def __init__(self, parent: QObject = None, **kwargs):
|
|
super().__init__(parent, **kwargs)
|
|
self.fluentIcon = None
|
|
|
|
@__init__.register
|
|
def _(self, text: str, parent: QObject = None, **kwargs):
|
|
super().__init__(text, parent, **kwargs)
|
|
self.fluentIcon = None
|
|
|
|
@__init__.register
|
|
def _(self, icon: QIcon, text: str, parent: QObject = None, **kwargs):
|
|
super().__init__(icon, text, parent, **kwargs)
|
|
self.fluentIcon = None
|
|
|
|
@__init__.register
|
|
def _(self, icon: FluentIconBase, text: str, parent: QObject = None, **kwargs):
|
|
super().__init__(icon.icon(), text, parent, **kwargs)
|
|
self.fluentIcon = icon
|
|
|
|
def icon(self) -> QIcon:
|
|
if self.fluentIcon:
|
|
return Icon(self.fluentIcon)
|
|
|
|
return super().icon()
|
|
|
|
def setIcon(self, icon: Union[FluentIconBase, QIcon]):
|
|
if isinstance(icon, FluentIconBase):
|
|
self.fluentIcon = icon
|
|
icon = icon.icon()
|
|
|
|
super().setIcon(icon)
|