From 771f9d75612b60ec629f3742d28947e7a63cb590 Mon Sep 17 00:00:00 2001
From: ChinaIceF <1489423523@qq.com>
Date: Fri, 25 Oct 2024 19:18:42 +0800
Subject: [PATCH 1/4] refactor: opt naming style in `parser.py`
---
.../components/page_icons/page_icons.py | 6 ++--
siui/core/globals.py | 2 +-
siui/gui/icons/parser.py | 28 +++++++++++++------
3 files changed, 23 insertions(+), 13 deletions(-)
diff --git a/examples/Gallery for siui/components/page_icons/page_icons.py b/examples/Gallery for siui/components/page_icons/page_icons.py
index 8688e40..67c0318 100644
--- a/examples/Gallery for siui/components/page_icons/page_icons.py
+++ b/examples/Gallery for siui/components/page_icons/page_icons.py
@@ -77,7 +77,7 @@ def __init__(self, *args, **kwargs):
self.package_selection_combobox = SiComboBox(self)
self.package_selection_combobox.resize(256, 32)
self.package_selection_combobox.addOption("所有图标包", (None,))
- for package_name in SiGlobal.siui.iconpack.get_class_names():
+ for package_name in SiGlobal.siui.iconpack.getClassNames():
self.package_selection_combobox.addOption(package_name)
self.package_selection_combobox.valueChanged.connect(self.on_package_changed)
self.package_selection_combobox.menu().setShowIcon(False)
@@ -156,7 +156,7 @@ def __init__(self, *args, **kwargs):
def on_package_changed(self, package_name):
if package_name == (None,):
package_name = None
- self.icon_dict = SiGlobal.siui.iconpack.get_dict(package_name)
+ self.icon_dict = SiGlobal.siui.iconpack.getDict(package_name)
self.load_icon_page_to(0)
def on_search_text_changed(self, text):
@@ -200,7 +200,7 @@ def load_icon_page_to(self, page_index, fade_ani=True):
svg_button.colorGroup().assign(SiColor.BUTTON_OFF,
svg_button.getColor(SiColor.INTERFACE_BG_C))
svg_button.attachment().setSvgSize(32, 32)
- svg_button.attachment().load(icon_pack.get_from_data(value, self.getColor(SiColor.SVG_NORMAL)))
+ svg_button.attachment().load(icon_pack.getFromData(value, self.getColor(SiColor.SVG_NORMAL)))
svg_button.setFixedSize(96, 96)
svg_button.setHint(
f"{key}
"
diff --git a/siui/core/globals.py b/siui/core/globals.py
index 5f4cfb9..99e5d6b 100644
--- a/siui/core/globals.py
+++ b/siui/core/globals.py
@@ -21,7 +21,7 @@ class SiliconUIGlobal:
# 值为 SVG信息的 bytes
icons = {}
iconpack = GlobalIconPack()
- iconpack.set_default_color(colors.fromToken(SiColor.SVG_NORMAL))
+ iconpack.setDefaultColor(colors.fromToken(SiColor.SVG_NORMAL))
# 样式表字典,储存所有动态样式表
# 值为字符串
diff --git a/siui/gui/icons/parser.py b/siui/gui/icons/parser.py
index 3604d6c..fb1f9b5 100644
--- a/siui/gui/icons/parser.py
+++ b/siui/gui/icons/parser.py
@@ -1,5 +1,7 @@
import os
+from PyQt5.QtCore import QByteArray
+
class GlobalIconPack:
current_module_path = os.path.dirname(os.path.abspath(__file__))
@@ -16,16 +18,20 @@ def __init__(self):
# load internal icon packages
self.reload_internals()
- def set_default_color(self, code):
+ def setDefaultColor(self, code) -> None:
self.default_color = code
- def reload_internals(self):
+ @property
+ def defaultColor(self) -> str:
+ return self.default_color
+
+ def reload_internals(self) -> None:
for package_filename in os.listdir(self.package_folder_path):
full_path = os.path.join(self.package_folder_path, package_filename)
if os.path.isfile(full_path):
self.load_from_file(full_path)
- def load_from_file(self, path):
+ def load_from_file(self, path) -> None:
class_name = os.path.basename(path)
self.append_class(class_name)
with open(path, encoding="utf-8") as file:
@@ -39,24 +45,28 @@ def load_from_file(self, path):
icon_name, icon_data = line.split("////")
self.append(icon_name, icon_data, class_name)
- def append_class(self, class_name, force=False):
+ def append_class(self, class_name, force=False) -> None:
if class_name in self.icons_classified.keys() and (force is False):
raise ValueError(f"Class name {class_name} is already exist.")
self.icons_classified[class_name] = {}
- def append(self, name, data, class_name: str = "__unclassified__"):
+ def append(self, name, data, class_name: str = "__unclassified__") -> None:
self.icons[name] = data
self.icons_classified[class_name][name] = data
- def get(self, name, color_code: str = None):
+ def get(self, name, color_code: str = None) -> bytes:
color_code = self.default_color if color_code is None else color_code
return self.icons[name].replace("<<>>", color_code).encode()
- def get_from_data(self, data, color_code: str = None):
+ def getFromData(self, data, color_code: str = None) -> bytes:
color_code = self.default_color if color_code is None else color_code
return data.replace("<<>>", color_code).encode()
- def get_dict(self, class_name=None):
+ def getByteArray(self, name, color_code: str = None) -> QByteArray:
+ svg_bytes = self.get(name, color_code)
+ return QByteArray(svg_bytes)
+
+ def getDict(self, class_name=None) -> dict:
"""
Get dictionary of an icon package.
If class name is assigned, returns the specific package dictionary.
@@ -67,5 +77,5 @@ def get_dict(self, class_name=None):
else:
return self.icons_classified[class_name]
- def get_class_names(self):
+ def getClassNames(self) -> dict.keys:
return self.icons_classified.keys()
From 5963a09e46683664dd0a6e6dbb8a7b9ba8766b48 Mon Sep 17 00:00:00 2001
From: ChinaIceF <1489423523@qq.com>
Date: Fri, 25 Oct 2024 21:28:27 +0800
Subject: [PATCH 2/4] feat: make `SiColor.toArray` now accepts color format
---
siui/core/color.py | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/siui/core/color.py b/siui/core/color.py
index d89950b..bc2d352 100644
--- a/siui/core/color.py
+++ b/siui/core/color.py
@@ -103,14 +103,24 @@ def RGB_to_RGBA(code: str):
@classmethod
def toArray(cls,
- code: str):
+ code: str,
+ c_format: str = "argb"):
"""
transform `#AARRGGBB` or `#RRGGBB` into `array(A, R, G, B, dtype=int16)`
"""
code = cls.RGB_to_RGBA(code)
code = code.lstrip("#")
a, r, g, b = int(code[0:2], 16), int(code[2:4], 16), int(code[4:6], 16), int(code[6:8], 16)
- return numpy.array([a, r, g, b], dtype=numpy.int16)
+
+ c_format = c_format.lower()
+ if c_format not in ["rgba", "argb", "rgb"]:
+ raise ValueError(f"{c_format} is not a valid format (rgba, argb, rgb)")
+ if c_format == "rgba":
+ return numpy.array([r, g, b, a], dtype=numpy.int16)
+ if c_format == "argb":
+ return numpy.array([a, r, g, b], dtype=numpy.int16)
+ if c_format == "rgb":
+ return numpy.array([r, g, b], dtype=numpy.int16)
@staticmethod
def toCode(value: Union[numpy.ndarray, list], force_rgba=False):
@@ -125,7 +135,6 @@ def toCode(value: Union[numpy.ndarray, list], force_rgba=False):
if (force_rgba is True) or (a != 255):
return f"#{int(a):02X}{int(r):02X}{int(g):02X}{int(b):02X}"
-
else:
return f"#{int(r):02X}{int(g):02X}{int(b):02X}"
From 390c45b17872a1b9af50994f4c64887a67c6a484 Mon Sep 17 00:00:00 2001
From: ChinaIceF <1489423523@qq.com>
Date: Fri, 25 Oct 2024 21:28:49 +0800
Subject: [PATCH 3/4] refactor: use `PushButtonStyleData` as dataclass of
SiPushButton
---
siui/components/button.py | 104 +++++++++++++++++++++++---------------
1 file changed, 64 insertions(+), 40 deletions(-)
diff --git a/siui/components/button.py b/siui/components/button.py
index 763b737..eaad806 100644
--- a/siui/components/button.py
+++ b/siui/components/button.py
@@ -2,6 +2,8 @@
# replace button once it's done. Now it's draft, code may be ugly and verbose temporarily.
from __future__ import annotations
+from dataclasses import dataclass
+
from PyQt5.QtCore import QEvent, QRect, QRectF, Qt
from PyQt5.QtGui import QColor, QIcon, QPainter, QPainterPath, QPaintEvent
from PyQt5.QtWidgets import QPushButton, QWidget
@@ -10,70 +12,83 @@
from siui.gui import SiFont
+@dataclass
+class PushButtonStyleData:
+ idle_color = SiColor.toArray("#00FFFFFF")
+ hover_color = SiColor.toArray("#10FFFFFF")
+ click_color = SiColor.toArray("#40FFFFFF")
+ background_color = SiColor.toArray("#2d2932", "rgba")
+ button_color = SiColor.toArray("#4C4554", "rgba")
+ border_radius: int = 4
+ border_inner_radius: int = 3
+ border_height: int = 3
+
+
class SiPushButtonRefactor(QPushButton):
def __init__(self, parent: QWidget | None = None) -> None:
super().__init__(parent)
+ self.style_data = PushButtonStyleData()
self._initStyle()
- self.idle_color = SiColor.toArray("#00FFFFFF")
- self.hover_color = SiColor.toArray("#10FFFFFF")
- self.click_color = SiColor.toArray("#40FFFFFF")
-
self.animation = SiExpAnimation(self)
self.animation.setFactor(1/8)
self.animation.setBias(0.2)
- self.animation.setTarget(self.idle_color)
- self.animation.setCurrent(self.idle_color)
+ self.animation.setTarget(self.style_data.idle_color)
+ self.animation.setCurrent(self.style_data.idle_color)
self.animation.ticked.connect(self.animate)
self.clicked.connect(self._onButtonClicked)
+ def _initStyle(self):
+ self.setFont(SiFont.tokenized(GlobalFont.S_NORMAL))
+ self.setStyleSheet("color: #DFDFDF;")
+
@classmethod
def withText(cls, text: str, parent: QWidget | None = None) -> "SiPushButton":
- cls = cls(parent)
- cls.setText(text)
- return cls
+ obj = cls(parent)
+ obj.setText(text)
+ return obj
@classmethod
def withIcon(cls, icon: QIcon, parent: QWidget | None = None) -> "SiPushButton":
- cls = cls(parent)
- cls.setIcon(icon)
- return cls
+ obj = cls(parent)
+ obj.setIcon(icon)
+ return obj
@classmethod
def withTextAndIcon(cls, text: str, icon: str, parent: QWidget | None = None) -> "SiPushButton":
- cls = cls(parent)
- cls.setText(text)
- cls.setIcon(icon)
- return cls
-
- def _initStyle(self):
- self.setFont(SiFont.tokenized(GlobalFont.S_NORMAL))
- self.setStyleSheet("color: #DFDFDF;")
-
+ obj = cls(parent)
+ obj.setText(text)
+ obj.setIcon(QIcon(icon))
+ return obj
@property
def bottomBorderHeight(self) -> int:
- return round(3)
+ return self.style_data.border_height
- @staticmethod
- def _drawBackgroundPath(rect: QRect) -> QPainterPath:
+ @property
+ def styleData(self) -> PushButtonStyleData:
+ return self.style_data
+
+ def _drawBackgroundPath(self, rect: QRect) -> QPainterPath:
+ radius = self.style_data.border_radius
path = QPainterPath()
- path.addRoundedRect(QRectF(0, 0, rect.width(), rect.height()), 4, 4)
+ path.addRoundedRect(QRectF(0, 0, rect.width(), rect.height()), radius, radius)
return path
def _drawBackgroundRect(self, painter: QPainter, rect: QRect) -> None:
- painter.setBrush(QColor("#2D2932"))
+ painter.setBrush(QColor(*self.style_data.background_color))
painter.drawPath(self._drawBackgroundPath(rect))
def _drawButtonPath(self, rect: QRect) -> QPainterPath:
+ radius = self.style_data.border_inner_radius
path = QPainterPath()
- path.addRoundedRect(QRectF(0, 0, rect.width(), rect.height() - self.bottomBorderHeight), 3, 3)
+ path.addRoundedRect(QRectF(0, 0, rect.width(), rect.height() - self.bottomBorderHeight), radius, radius)
return path
def _drawButtonRect(self, painter: QPainter, rect: QRect) -> None:
- painter.setBrush(QColor("#4C4554"))
+ painter.setBrush(QColor(*self.style_data.button_color))
painter.drawPath(self._drawButtonPath(rect))
def _drawHighLightRect(self, painter: QPainter, rect: QRect) -> None:
@@ -86,22 +101,25 @@ def _drawTextRect(self, painter: QPainter, rect: QRect) -> None:
painter.drawText(rect, Qt.AlignCenter, self.text())
def _onButtonClicked(self) -> None:
- self.animation.setCurrent(self.click_color)
+ self.animation.setCurrent(self.style_data.click_color)
self.animation.start()
def _showToolTip(self) -> None:
- if self.toolTip() != "" and "TOOL_TIP" in SiGlobal.siui.windows:
- SiGlobal.siui.windows["TOOL_TIP"].setNowInsideOf(self)
- SiGlobal.siui.windows["TOOL_TIP"].show_()
+ tool_tip_window = SiGlobal.siui.windows.get("TOOL_TIP")
+ if tool_tip_window is not None and self.toolTip() != "":
+ tool_tip_window.setNowInsideOf(self)
+ tool_tip_window.show_()
def _hideToolTip(self) -> None:
- if self.toolTip() != "" and "TOOL_TIP" in SiGlobal.siui.windows:
- SiGlobal.siui.windows["TOOL_TIP"].setNowInsideOf(None)
- SiGlobal.siui.windows["TOOL_TIP"].hide_()
+ tool_tip_window = SiGlobal.siui.windows.get("TOOL_TIP")
+ if tool_tip_window is not None and self.toolTip() != "":
+ tool_tip_window.setNowInsideOf(None)
+ tool_tip_window.hide_()
def _updateToolTip(self) -> None:
- if SiGlobal.siui.windows["TOOL_TIP"].nowInsideOf() == self:
- SiGlobal.siui.windows["TOOL_TIP"].setText(self.toolTip())
+ tool_tip_window = SiGlobal.siui.windows.get("TOOL_TIP")
+ if tool_tip_window is not None and tool_tip_window.nowInsideOf() == self:
+ tool_tip_window.setText(self.toolTip())
def animate(self, _) -> None:
self.update()
@@ -110,6 +128,12 @@ def setToolTip(self, tooltip) -> None:
super().setToolTip(tooltip)
self._updateToolTip()
+ def setButtonColor(self, code: str) -> None:
+ self.style_data.button_color = SiColor.toArray(code, "rgba")
+
+ def setBackgroundColor(self, code: str) -> None:
+ self.style_data.background_color = SiColor.toArray(code, "rgba")
+
def event(self, event):
if event.type() == QEvent.ToolTip:
return True # 忽略工具提示事件
@@ -117,14 +141,14 @@ def event(self, event):
def enterEvent(self, event) -> None:
super().enterEvent(event)
- self.animation.setTarget(self.hover_color)
+ self.animation.setTarget(self.style_data.hover_color)
self.animation.start()
self._showToolTip()
self._updateToolTip()
def leaveEvent(self, event) -> None:
super().leaveEvent(event)
- self.animation.setTarget(self.idle_color)
+ self.animation.setTarget(self.style_data.idle_color)
self.animation.start()
self._hideToolTip()
@@ -138,7 +162,7 @@ def paintEvent(self, event: QPaintEvent) -> None:
painter.setPen(Qt.PenStyle.NoPen)
rect = self.rect()
- text_rect = QRect(0, 0, self.width(), self.height() - 4)
+ text_rect = QRect(0, 0, self.width(), self.height() - self.style_data.border_height - 1)
self._drawBackgroundRect(painter, rect)
self._drawButtonRect(painter, rect)
self._drawHighLightRect(painter, rect)
From 3b04105c950e3a357cb0c410daf45f0b6b2d6c83 Mon Sep 17 00:00:00 2001
From: ChinaIceF <1489423523@qq.com>
Date: Sat, 26 Oct 2024 11:42:57 +0800
Subject: [PATCH 4/4] refactor: abst `PushButtonStyleData`
---
siui/components/button.py | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/siui/components/button.py b/siui/components/button.py
index eaad806..74136e1 100644
--- a/siui/components/button.py
+++ b/siui/components/button.py
@@ -130,9 +130,23 @@ def setToolTip(self, tooltip) -> None:
def setButtonColor(self, code: str) -> None:
self.style_data.button_color = SiColor.toArray(code, "rgba")
+ self.update()
def setBackgroundColor(self, code: str) -> None:
self.style_data.background_color = SiColor.toArray(code, "rgba")
+ self.update()
+
+ def setBorderRadius(self, r: int) -> None:
+ self.style_data.border_radius = r
+ self.update()
+
+ def setBorderInnerRadius(self, r: int) -> None:
+ self.style_data.border_inner_radius = r
+ self.update()
+
+ def setBorderHeight(self, h: int) -> None:
+ self.style_data.border_height = h
+ self.update()
def event(self, event):
if event.type() == QEvent.ToolTip: