提交 2657cfeb 编写于 作者: 之一Yo's avatar 之一Yo

添加图标界面

上级 cae37b4f
...@@ -18,6 +18,7 @@ class Icon(FluentIconBase, Enum): ...@@ -18,6 +18,7 @@ class Icon(FluentIconBase, Enum):
CHECKBOX = "CheckBox" CHECKBOX = "CheckBox"
DOCUMENT = "Document" DOCUMENT = "Document"
CONSTRACT = "Constract" CONSTRACT = "Constract"
EMOJI_TAB_SYMBOLS = "EmojiTabSymbols"
def path(self, theme=Theme.AUTO): def path(self, theme=Theme.AUTO):
if theme == Theme.AUTO: if theme == Theme.AUTO:
......
...@@ -13,4 +13,5 @@ class Translator(QObject): ...@@ -13,4 +13,5 @@ class Translator(QObject):
self.statusInfo = self.tr('Status & info') self.statusInfo = self.tr('Status & info')
self.scroll = self.tr('Scrolling') self.scroll = self.tr('Scrolling')
self.layout = self.tr('Layout') self.layout = self.tr('Layout')
self.text = self.tr('Text') self.text = self.tr('Text')
\ No newline at end of file self.icons = self.tr('Icons')
\ No newline at end of file
# coding: utf-8
from queue import Queue
class Trie:
""" String trie """
def __init__(self):
self.key = ''
self.value = None
self.children = [None] * 26
self.isEnd = False
def insert(self, key: str, value):
""" insert item """
key = key.lower()
node = self
for c in key:
i = ord(c) - 97
if not 0 <= i < 26:
return
if not node.children[i]:
node.children[i] = Trie()
node = node.children[i]
node.isEnd = True
node.key = key
node.value = value
def get(self, key, default=None):
""" get value of key """
node = self.searchPrefix(key)
if not (node and node.isEnd):
return default
return node.value
def searchPrefix(self, prefix):
""" search node matchs the prefix """
prefix = prefix.lower()
node = self
for c in prefix:
i = ord(c) - 97
if not (0 <= i < 26 and node.children[i]):
return None
node = node.children[i]
return node
def items(self, prefix):
""" search items match the prefix """
node = self.searchPrefix(prefix)
if not node:
return []
q = Queue()
result = []
q.put(node)
while not q.empty():
node = q.get()
if node.isEnd:
result.append((node.key, node.value))
for c in node.children:
if c:
q.put(c)
return result
...@@ -155,6 +155,27 @@ ...@@ -155,6 +155,27 @@
<translation>源代碼</translation> <translation>源代碼</translation>
</message> </message>
</context> </context>
<context>
<name>IconCardView</name>
<message>
<location filename="../../view/icon_interface.py" line="125"/>
<source>Fluent Icons Library</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>IconInfoPanel</name>
<message>
<location filename="../../view/icon_interface.py" line="83"/>
<source>Icon name</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../view/icon_interface.py" line="85"/>
<source>Enum member</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>LayoutInterface</name> <name>LayoutInterface</name>
<message> <message>
...@@ -218,63 +239,76 @@ ...@@ -218,63 +239,76 @@
<translation>D4C</translation> <translation>D4C</translation>
</message> </message>
</context> </context>
<context>
<name>LineEdit</name>
<message>
<location filename="../../view/icon_interface.py" line="23"/>
<source>Search icons</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>MainWindow</name> <name>MainWindow</name>
<message> <message>
<location filename="../../view/main_window.py" line="132"/> <location filename="../../view/main_window.py" line="136"/>
<source>Home</source> <source>Home</source>
<translation>主頁</translation> <translation>主頁</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="140"/> <location filename="../../view/main_window.py" line="150"/>
<source>Basic input</source> <source>Basic input</source>
<translation>基本輸入</translation> <translation>基本輸入</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="147"/> <location filename="../../view/main_window.py" line="157"/>
<source>Dialogs</source> <source>Dialogs</source>
<translation>對話框</translation> <translation>對話框</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="154"/> <location filename="../../view/main_window.py" line="164"/>
<source>Layout</source> <source>Layout</source>
<translation>佈局</translation> <translation>佈局</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="168"/> <location filename="../../view/main_window.py" line="178"/>
<source>Menus</source> <source>Menus</source>
<translation>菜單</translation> <translation>菜單</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="161"/> <location filename="../../view/main_window.py" line="171"/>
<source>Material</source> <source>Material</source>
<translation>材料</translation> <translation>材料</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="175"/> <location filename="../../view/main_window.py" line="185"/>
<source>Scrolling</source> <source>Scrolling</source>
<translation>滾動</translation> <translation>滾動</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="182"/> <location filename="../../view/main_window.py" line="192"/>
<source>Status &amp; info</source> <source>Status &amp; info</source>
<translation>狀態和信息</translation> <translation>狀態和信息</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="250"/> <location filename="../../view/main_window.py" line="260"/>
<source>This is a help message</source> <source>This is a help message</source>
<translation>一條友善的提示</translation> <translation>一條友善的提示</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="250"/> <location filename="../../view/main_window.py" line="260"/>
<source>You clicked a customized navigation widget. You can add more custom widgets by calling `NavigationInterface.addWidget()` 😉</source> <source>You clicked a customized navigation widget. You can add more custom widgets by calling `NavigationInterface.addWidget()` 😉</source>
<translation>你點擊了一個自定義的導航項你可以通過 `NavigationInterface.addWidget()` 添加更多的自定義導航項</translation> <translation>你點擊了一個自定義的導航項你可以通過 `NavigationInterface.addWidget()` 添加更多的自定義導航項</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="189"/> <location filename="../../view/main_window.py" line="199"/>
<source>Text</source> <source>Text</source>
<translation>文本</translation> <translation>文本</translation>
</message> </message>
<message>
<location filename="../../view/main_window.py" line="142"/>
<source>Icons</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>MaterialInterface</name> <name>MaterialInterface</name>
...@@ -739,42 +773,42 @@ ...@@ -739,42 +773,42 @@
<context> <context>
<name>TextInterface</name> <name>TextInterface</name>
<message> <message>
<location filename="../../view/text_interface.py" line="23"/> <location filename="../../view/text_interface.py" line="20"/>
<source>ko no dio da</source> <source>ko no dio da</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../view/text_interface.py" line="25"/> <location filename="../../view/text_interface.py" line="22"/>
<source>A LineEdit with a clear button</source> <source>A LineEdit with a clear button</source>
<translation>帶清空按鈕的 LineEdit</translation> <translation>帶清空按鈕的 LineEdit</translation>
</message> </message>
<message> <message>
<location filename="../../view/text_interface.py" line="39"/> <location filename="../../view/text_interface.py" line="36"/>
<source>A DoubleSpinBox with a spin button</source> <source>A DoubleSpinBox with a spin button</source>
<translation>帶調節按鈕的 DoubleSpinBox</translation> <translation>帶調節按鈕的 DoubleSpinBox</translation>
</message> </message>
<message> <message>
<location filename="../../view/text_interface.py" line="46"/> <location filename="../../view/text_interface.py" line="43"/>
<source>A DateEdit with a spin button</source> <source>A DateEdit with a spin button</source>
<translation>帶調節按鈕的 DateEdit</translation> <translation>帶調節按鈕的 DateEdit</translation>
</message> </message>
<message> <message>
<location filename="../../view/text_interface.py" line="53"/> <location filename="../../view/text_interface.py" line="50"/>
<source>A TimeEdit with a spin button</source> <source>A TimeEdit with a spin button</source>
<translation>帶調節按鈕的 TimeEdit</translation> <translation>帶調節按鈕的 TimeEdit</translation>
</message> </message>
<message> <message>
<location filename="../../view/text_interface.py" line="60"/> <location filename="../../view/text_interface.py" line="57"/>
<source>A DateTimeEdit with a spin button</source> <source>A DateTimeEdit with a spin button</source>
<translation>帶調節按鈕的 DateTimeEdit</translation> <translation>帶調節按鈕的 DateTimeEdit</translation>
</message> </message>
<message> <message>
<location filename="../../view/text_interface.py" line="32"/> <location filename="../../view/text_interface.py" line="29"/>
<source>A SpinBox with a spin button</source> <source>A SpinBox with a spin button</source>
<translation>帶調節按鈕的 SpinBox</translation> <translation>帶調節按鈕的 SpinBox</translation>
</message> </message>
<message> <message>
<location filename="../../view/text_interface.py" line="71"/> <location filename="../../view/text_interface.py" line="68"/>
<source>A simple TextEdit</source> <source>A simple TextEdit</source>
<translation>富文本框</translation> <translation>富文本框</translation>
</message> </message>
...@@ -844,5 +878,10 @@ ...@@ -844,5 +878,10 @@
<source>Text</source> <source>Text</source>
<translation>文本</translation> <translation>文本</translation>
</message> </message>
<message>
<location filename="../../common/translator.py" line="17"/>
<source>Icons</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
</TS> </TS>
\ No newline at end of file
...@@ -155,6 +155,27 @@ ...@@ -155,6 +155,27 @@
<translation>源代码</translation> <translation>源代码</translation>
</message> </message>
</context> </context>
<context>
<name>IconCardView</name>
<message>
<location filename="../../view/icon_interface.py" line="125"/>
<source>Fluent Icons Library</source>
<translation>流畅图标库</translation>
</message>
</context>
<context>
<name>IconInfoPanel</name>
<message>
<location filename="../../view/icon_interface.py" line="83"/>
<source>Icon name</source>
<translation>图标名字</translation>
</message>
<message>
<location filename="../../view/icon_interface.py" line="85"/>
<source>Enum member</source>
<translation>枚举成员</translation>
</message>
</context>
<context> <context>
<name>LayoutInterface</name> <name>LayoutInterface</name>
<message> <message>
...@@ -218,63 +239,76 @@ ...@@ -218,63 +239,76 @@
<translation>D4C</translation> <translation>D4C</translation>
</message> </message>
</context> </context>
<context>
<name>LineEdit</name>
<message>
<location filename="../../view/icon_interface.py" line="23"/>
<source>Search icons</source>
<translation>搜索图标</translation>
</message>
</context>
<context> <context>
<name>MainWindow</name> <name>MainWindow</name>
<message> <message>
<location filename="../../view/main_window.py" line="132"/> <location filename="../../view/main_window.py" line="136"/>
<source>Home</source> <source>Home</source>
<translation>主页</translation> <translation>主页</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="140"/> <location filename="../../view/main_window.py" line="150"/>
<source>Basic input</source> <source>Basic input</source>
<translation>基本输入</translation> <translation>基本输入</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="147"/> <location filename="../../view/main_window.py" line="157"/>
<source>Dialogs</source> <source>Dialogs</source>
<translation>对话框</translation> <translation>对话框</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="154"/> <location filename="../../view/main_window.py" line="164"/>
<source>Layout</source> <source>Layout</source>
<translation>布局</translation> <translation>布局</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="168"/> <location filename="../../view/main_window.py" line="178"/>
<source>Menus</source> <source>Menus</source>
<translation>菜单</translation> <translation>菜单</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="161"/> <location filename="../../view/main_window.py" line="171"/>
<source>Material</source> <source>Material</source>
<translation>材料</translation> <translation>材料</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="175"/> <location filename="../../view/main_window.py" line="185"/>
<source>Scrolling</source> <source>Scrolling</source>
<translation>滚动</translation> <translation>滚动</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="182"/> <location filename="../../view/main_window.py" line="192"/>
<source>Status &amp; info</source> <source>Status &amp; info</source>
<translation>状态和信息</translation> <translation>状态和信息</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="250"/> <location filename="../../view/main_window.py" line="260"/>
<source>This is a help message</source> <source>This is a help message</source>
<translation>一条友善的提示</translation> <translation>一条友善的提示</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="250"/> <location filename="../../view/main_window.py" line="260"/>
<source>You clicked a customized navigation widget. You can add more custom widgets by calling `NavigationInterface.addWidget()` 😉</source> <source>You clicked a customized navigation widget. You can add more custom widgets by calling `NavigationInterface.addWidget()` 😉</source>
<translation>你点击了一个自定义的导航项你可以通过 `NavigationInterface.addWidget()` 添加更多的自定义导航项</translation> <translation>你点击了一个自定义的导航项你可以通过 `NavigationInterface.addWidget()` 添加更多的自定义导航项</translation>
</message> </message>
<message> <message>
<location filename="../../view/main_window.py" line="189"/> <location filename="../../view/main_window.py" line="199"/>
<source>Text</source> <source>Text</source>
<translation>文本</translation> <translation>文本</translation>
</message> </message>
<message>
<location filename="../../view/main_window.py" line="142"/>
<source>Icons</source>
<translation>图标</translation>
</message>
</context> </context>
<context> <context>
<name>MaterialInterface</name> <name>MaterialInterface</name>
...@@ -739,42 +773,42 @@ ...@@ -739,42 +773,42 @@
<context> <context>
<name>TextInterface</name> <name>TextInterface</name>
<message> <message>
<location filename="../../view/text_interface.py" line="23"/> <location filename="../../view/text_interface.py" line="20"/>
<source>ko no dio da</source> <source>ko no dio da</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../view/text_interface.py" line="25"/> <location filename="../../view/text_interface.py" line="22"/>
<source>A LineEdit with a clear button</source> <source>A LineEdit with a clear button</source>
<translation>带清空按钮的 LineEdit</translation> <translation>带清空按钮的 LineEdit</translation>
</message> </message>
<message> <message>
<location filename="../../view/text_interface.py" line="39"/> <location filename="../../view/text_interface.py" line="36"/>
<source>A DoubleSpinBox with a spin button</source> <source>A DoubleSpinBox with a spin button</source>
<translation>带调节按钮的 DoubleSpinBox</translation> <translation>带调节按钮的 DoubleSpinBox</translation>
</message> </message>
<message> <message>
<location filename="../../view/text_interface.py" line="46"/> <location filename="../../view/text_interface.py" line="43"/>
<source>A DateEdit with a spin button</source> <source>A DateEdit with a spin button</source>
<translation>带调节按钮的 DateEdit</translation> <translation>带调节按钮的 DateEdit</translation>
</message> </message>
<message> <message>
<location filename="../../view/text_interface.py" line="53"/> <location filename="../../view/text_interface.py" line="50"/>
<source>A TimeEdit with a spin button</source> <source>A TimeEdit with a spin button</source>
<translation>带调节按钮的 TimeEdit</translation> <translation>带调节按钮的 TimeEdit</translation>
</message> </message>
<message> <message>
<location filename="../../view/text_interface.py" line="60"/> <location filename="../../view/text_interface.py" line="57"/>
<source>A DateTimeEdit with a spin button</source> <source>A DateTimeEdit with a spin button</source>
<translation>带调节按钮的 DateTimeEdit</translation> <translation>带调节按钮的 DateTimeEdit</translation>
</message> </message>
<message> <message>
<location filename="../../view/text_interface.py" line="32"/> <location filename="../../view/text_interface.py" line="29"/>
<source>A SpinBox with a spin button</source> <source>A SpinBox with a spin button</source>
<translation>带调节按钮的 SpinBox</translation> <translation>带调节按钮的 SpinBox</translation>
</message> </message>
<message> <message>
<location filename="../../view/text_interface.py" line="71"/> <location filename="../../view/text_interface.py" line="68"/>
<source>A simple TextEdit</source> <source>A simple TextEdit</source>
<translation>富文本框</translation> <translation>富文本框</translation>
</message> </message>
...@@ -844,5 +878,10 @@ ...@@ -844,5 +878,10 @@
<source>Text</source> <source>Text</source>
<translation>文本</translation> <translation>文本</translation>
</message> </message>
<message>
<location filename="../../common/translator.py" line="17"/>
<source>Icons</source>
<translation>图标</translation>
</message>
</context> </context>
</TS> </TS>
<?xml version="1.0" encoding="utf-8"?>
<svg id="" width="16" height="16" style="width:16px;height:16px;" version="1.1"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2048 2048" enable-background="new 0 0 2048 2048"
xml:space="preserve"><path fill="#000000" d="M1920 1287 l0 -135 l128 0 l0 384 l-384 0 l0 -128 l192 0 q-45 -60 -113 -94 q-68 -34 -143 -34 q-51 0 -98 15.5 q-47 15.5 -87 43.5 q-40 28 -70 67 q-30 39 -47 87 l-120 -42 q24 -67 66 -122 q42 -55 97.5 -94.5 q55.5 -39.5 121.5 -61 q66 -21.5 137 -21.5 q91 0 174 34.5 q83 34.5 146 100.5 ZM448 0 q93 0 174.5 35 q81.5 35 142.5 96 q61 61 96 142.5 q35 81.5 35 174.5 q0 93 -35 174.5 q-35 81.5 -96 142.5 q-61 61 -142.5 96 q-81.5 35 -174.5 35 q-93 0 -174.5 -35 q-81.5 -35 -142.5 -96 q-61 -61 -96 -142.5 q-35 -81.5 -35 -174.5 q0 -93 35 -174.5 q35 -81.5 96 -142.5 q61 -61 142.5 -96 q81.5 -35 174.5 -35 ZM128 448 q0 66 25 124.5 q25 58.5 68.5 102 q43.5 43.5 102 68.5 q58.5 25 124.5 25 q47 0 92 -13.5 q45 -13.5 84 -39.5 l-443 -443 q-26 39 -39.5 84 q-13.5 45 -13.5 92 ZM272 181 l443 443 q26 -39 39.5 -84 q13.5 -45 13.5 -92 q0 -66 -25.5 -124 q-25.5 -58 -69 -101.5 q-43.5 -43.5 -101.5 -69 q-58 -25.5 -124 -25.5 q-47 0 -92 13.5 q-45 13.5 -84 39.5 ZM1600 1920 q51 0 98 -15.5 q47 -15.5 86.5 -43.5 q39.5 -28 70 -67 q30.5 -39 47.5 -87 l120 42 q-24 67 -66 122 q-42 55 -97.5 94.5 q-55.5 39.5 -121.5 61 q-66 21.5 -137 21.5 q-91 0 -174 -34.5 q-83 -34.5 -146 -100.5 l0 135 l-128 0 l0 -384 l384 0 l0 128 l-192 0 q45 60 113 94 q68 34 143 34 ZM1600 890 l-370 -369 q-38 -38 -58 -86.5 q-20 -48.5 -20 -102.5 q0 -55 21 -104 q21 -49 57 -85.5 q36 -36.5 84.5 -57.5 q48.5 -21 104.5 -21 q51 0 97.5 18 q46.5 18 83.5 52 q37 -34 83.5 -52 q46.5 -18 97.5 -18 q55 0 104 21 q49 21 85 57.5 q36 36.5 57 85.5 q21 49 21 104 q0 54 -20 102.5 q-20 48.5 -58 86.5 l-370 369 ZM1420 192 q-29 0 -54.5 11 q-25.5 11 -44.5 30 q-19 19 -30 44.5 q-11 25.5 -11 54.5 q0 28 10.5 53 q10.5 25 30.5 45 l279 279 l279 -279 q41 -41 41 -98 q0 -29 -11 -54.5 q-11 -25.5 -30 -44.5 q-19 -19 -44.5 -30 q-25.5 -11 -54.5 -11 q-29 0 -53.5 10.5 q-24.5 10.5 -44.5 30.5 l-82 82 l-82 -82 q-20 -20 -45 -30.5 q-25 -10.5 -53 -10.5 ZM384 1152 l128 0 l0 384 l384 0 l0 128 l-384 0 l0 384 l-128 0 l0 -384 l-384 0 l0 -128 l384 0 l0 -384 Z"/></svg>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<svg id="" width="16" height="16" style="width:16px;height:16px;" version="1.1"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2048 2048" enable-background="new 0 0 2048 2048"
xml:space="preserve"><path fill="#ffffff" d="M1920 1287 l0 -135 l128 0 l0 384 l-384 0 l0 -128 l192 0 q-45 -60 -113 -94 q-68 -34 -143 -34 q-51 0 -98 15.5 q-47 15.5 -87 43.5 q-40 28 -70 67 q-30 39 -47 87 l-120 -42 q24 -67 66 -122 q42 -55 97.5 -94.5 q55.5 -39.5 121.5 -61 q66 -21.5 137 -21.5 q91 0 174 34.5 q83 34.5 146 100.5 ZM448 0 q93 0 174.5 35 q81.5 35 142.5 96 q61 61 96 142.5 q35 81.5 35 174.5 q0 93 -35 174.5 q-35 81.5 -96 142.5 q-61 61 -142.5 96 q-81.5 35 -174.5 35 q-93 0 -174.5 -35 q-81.5 -35 -142.5 -96 q-61 -61 -96 -142.5 q-35 -81.5 -35 -174.5 q0 -93 35 -174.5 q35 -81.5 96 -142.5 q61 -61 142.5 -96 q81.5 -35 174.5 -35 ZM128 448 q0 66 25 124.5 q25 58.5 68.5 102 q43.5 43.5 102 68.5 q58.5 25 124.5 25 q47 0 92 -13.5 q45 -13.5 84 -39.5 l-443 -443 q-26 39 -39.5 84 q-13.5 45 -13.5 92 ZM272 181 l443 443 q26 -39 39.5 -84 q13.5 -45 13.5 -92 q0 -66 -25.5 -124 q-25.5 -58 -69 -101.5 q-43.5 -43.5 -101.5 -69 q-58 -25.5 -124 -25.5 q-47 0 -92 13.5 q-45 13.5 -84 39.5 ZM1600 1920 q51 0 98 -15.5 q47 -15.5 86.5 -43.5 q39.5 -28 70 -67 q30.5 -39 47.5 -87 l120 42 q-24 67 -66 122 q-42 55 -97.5 94.5 q-55.5 39.5 -121.5 61 q-66 21.5 -137 21.5 q-91 0 -174 -34.5 q-83 -34.5 -146 -100.5 l0 135 l-128 0 l0 -384 l384 0 l0 128 l-192 0 q45 60 113 94 q68 34 143 34 ZM1600 890 l-370 -369 q-38 -38 -58 -86.5 q-20 -48.5 -20 -102.5 q0 -55 21 -104 q21 -49 57 -85.5 q36 -36.5 84.5 -57.5 q48.5 -21 104.5 -21 q51 0 97.5 18 q46.5 18 83.5 52 q37 -34 83.5 -52 q46.5 -18 97.5 -18 q55 0 104 21 q49 21 85 57.5 q36 36.5 57 85.5 q21 49 21 104 q0 54 -20 102.5 q-20 48.5 -58 86.5 l-370 369 ZM1420 192 q-29 0 -54.5 11 q-25.5 11 -44.5 30 q-19 19 -30 44.5 q-11 25.5 -11 54.5 q0 28 10.5 53 q10.5 25 30.5 45 l279 279 l279 -279 q41 -41 41 -98 q0 -29 -11 -54.5 q-11 -25.5 -30 -44.5 q-19 -19 -44.5 -30 q-25.5 -11 -54.5 -11 q-29 0 -53.5 10.5 q-24.5 10.5 -44.5 30.5 l-82 82 l-82 -82 q-20 -20 -45 -30.5 q-25 -10.5 -53 -10.5 ZM384 1152 l128 0 l0 384 l384 0 l0 128 l-384 0 l0 384 l-128 0 l0 -384 l-384 0 l0 -128 l384 0 l0 -384 Z"/></svg>
\ No newline at end of file
IconCard {
background-color: rgb(43, 43, 43);
border: 1px solid rgb(29, 29, 29);
border-radius: 6px;
}
IconCard > QLabel {
color: rgb(207, 207, 207);
font: 11px 'Segoe UI';
}
IconCard[isSelected=true] {
background-color: --ThemeColorPrimary;
}
IconCard[isSelected=true] > QLabel {
color: black;
}
#scrollWidget, #iconView {
background-color: rgb(32, 32, 32);
}
IconCardView {
background-color: transparent;
}
#iconLibraryLabel {
font: 14px 'Segoe UI Light', 'Microsoft YaHei';
background-color: transparent;
font-weight: 700;
color: white;
}
#iconView {
border: 1px solid rgb(36, 36, 36);
border-radius: 10px;
}
IconInfoPanel {
background-color: rgb(43, 43, 43);
border-left: 1px solid rgb(29, 29, 29);
border-top-right-radius: 10px;
border-bottom-right-radius: 10px;
}
IconInfoPanel>#nameLabel {
font: 15px 'Segoe UI';
font-weight: bold;
color: white;
}
IconInfoPanel>#subTitleLabel {
font: 14px 'Segoe UI', 'Microsoft YaHei';
color: white;
}
IconInfoPanel>QLabel {
font: 12px 'Segoe UI';
color: rgb(207, 207, 207);
}
QScrollBar {
background: transparent;
width: 4px;
margin-top: 10px;
margin-bottom: 0;
padding-right: 2px;
}
QScrollBar::sub-line {
background: transparent;
}
QScrollBar::add-line {
background: transparent;
}
QScrollBar::handle {
background: rgb(122, 122, 122);
border: 2px solid rgb(128, 128, 128);
border-radius: 1px;
min-height: 32px;
}
QScrollBar::add-page:vertical,
QScrollBar::sub-page:vertical {
background: none;
}
\ No newline at end of file
IconCard {
background-color: rgb(251, 251, 251);
border: 1px solid rgb(229, 229, 229);
border-radius: 6px;
}
IconCard > QLabel {
color: rgb(96, 96, 96);
font: 11px 'Segoe UI';
}
IconCard[isSelected=true] {
background-color: --ThemeColorPrimary;
}
IconCard[isSelected=true] > QLabel {
color: white;
}
#scrollWidget, #iconView {
background-color: rgb(243, 243, 243);
}
IconCardView {
background-color: transparent;
}
#iconView {
border: 1px solid rgb(234, 234, 234);
border-radius: 10px;
}
IconInfoPanel {
background-color: rgb(251, 251, 251);
border-left: 1px solid rgb(229, 229, 229);
border-top-right-radius: 10px;
border-bottom-right-radius: 10px;
}
IconInfoPanel > #nameLabel {
font: 15px 'Segoe UI';
font-weight: bold;
color: black;
}
IconInfoPanel > #subTitleLabel {
font: 14px 'Segoe UI', 'Microsoft YaHei';
color: black;
}
IconInfoPanel > QLabel {
font: 12px 'Segoe UI';
color: rgb(96, 96, 96);
}
#iconLibraryLabel {
font: 14px 'Segoe UI Light', 'Microsoft YaHei';
font-weight: 700;
background-color: transparent;
color: black;
}
QScrollBar {
background: transparent;
width: 4px;
margin-top: 10px;
margin-bottom: 0;
padding-right: 2px;
}
QScrollBar::sub-line {
background: transparent;
}
QScrollBar::add-line {
background: transparent;
}
QScrollBar::handle {
background: rgb(122, 122, 122);
border: 2px solid rgb(128, 128, 128);
border-radius: 1px;
min-height: 32px;
}
QScrollBar::add-page:vertical,
QScrollBar::sub-page:vertical {
background: none;
}
\ No newline at end of file
# coding:utf-8
from typing import List
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtWidgets import QApplication, QFrame, QVBoxLayout, QLabel, QWidget, QHBoxLayout
from qfluentwidgets import (FluentIcon, IconWidget, FlowLayout, isDarkTheme,
Theme, applyThemeColor, SmoothScrollArea, SearchLineEdit)
from .gallery_interface import GalleryInterface
from ..common.translator import Translator
from ..common.config import cfg
from ..common.trie import Trie
class LineEdit(SearchLineEdit):
""" Search line edit """
searchSignal = pyqtSignal(str)
clearSignal = pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
self.setPlaceholderText(self.tr('Search icons'))
self.setFixedWidth(304)
self.textChanged.connect(self.search)
class IconCard(QFrame):
""" Icon card """
clicked = pyqtSignal(FluentIcon)
def __init__(self, icon: FluentIcon, parent=None):
super().__init__(parent=parent)
self.icon = icon
self.isSelected = False
self.iconWidget = IconWidget(icon, self)
self.nameLabel = QLabel(self)
self.vBoxLayout = QVBoxLayout(self)
self.setFixedSize(96, 96)
self.vBoxLayout.setSpacing(0)
self.vBoxLayout.setContentsMargins(8, 28, 8, 0)
self.vBoxLayout.setAlignment(Qt.AlignTop)
self.iconWidget.setFixedSize(28, 28)
self.vBoxLayout.addWidget(self.iconWidget, 0, Qt.AlignHCenter)
self.vBoxLayout.addSpacing(14)
self.vBoxLayout.addWidget(self.nameLabel, 0, Qt.AlignHCenter)
text = self.nameLabel.fontMetrics().elidedText(icon.value, Qt.ElideRight, 78)
self.nameLabel.setText(text)
def mouseReleaseEvent(self, e):
if self.isSelected:
return
self.clicked.emit(self.icon)
def setSelected(self, isSelected: bool, force=False):
if isSelected == self.isSelected and not force:
return
self.isSelected = isSelected
if not isSelected:
self.iconWidget.setIcon(self.icon)
else:
icon = self.icon.icon(Theme.LIGHT if isDarkTheme() else Theme.DARK)
self.iconWidget.setIcon(icon)
self.setProperty('isSelected', isSelected)
self.setStyle(QApplication.style())
class IconInfoPanel(QFrame):
""" Icon info panel """
def __init__(self, icon: FluentIcon, parent=None):
super().__init__(parent=parent)
self.nameLabel = QLabel(icon.value, self)
self.iconWidget = IconWidget(icon, self)
self.iconNameTitleLabel = QLabel(self.tr('Icon name'), self)
self.iconNameLabel = QLabel(icon.value, self)
self.enumNameTitleLabel = QLabel(self.tr('Enum member'), self)
self.enumNameLabel = QLabel("FluentIcon." + icon.name, self)
self.vBoxLayout = QVBoxLayout(self)
self.vBoxLayout.setContentsMargins(16, 20, 16, 20)
self.vBoxLayout.setSpacing(0)
self.vBoxLayout.setAlignment(Qt.AlignTop)
self.vBoxLayout.addWidget(self.nameLabel)
self.vBoxLayout.addSpacing(16)
self.vBoxLayout.addWidget(self.iconWidget)
self.vBoxLayout.addSpacing(45)
self.vBoxLayout.addWidget(self.iconNameTitleLabel)
self.vBoxLayout.addSpacing(5)
self.vBoxLayout.addWidget(self.iconNameLabel)
self.vBoxLayout.addSpacing(34)
self.vBoxLayout.addWidget(self.enumNameTitleLabel)
self.vBoxLayout.addSpacing(5)
self.vBoxLayout.addWidget(self.enumNameLabel)
self.iconWidget.setFixedSize(48, 48)
self.setFixedWidth(216)
self.nameLabel.setObjectName('nameLabel')
self.iconNameTitleLabel.setObjectName('subTitleLabel')
self.enumNameTitleLabel.setObjectName('subTitleLabel')
def setIcon(self, icon: FluentIcon):
self.iconWidget.setIcon(icon)
self.nameLabel.setText(icon.value)
self.iconNameLabel.setText(icon.value)
self.enumNameLabel.setText("FluentIcon."+icon.name)
class IconCardView(QWidget):
""" Icon card view """
def __init__(self, parent=None):
super().__init__(parent=parent)
self.trie = Trie()
self.iconLibraryLabel = QLabel(self.tr('Fluent Icons Library'), self)
self.searchLineEdit = LineEdit(self)
self.view = QFrame(self)
self.scrollArea = SmoothScrollArea(self.view)
self.scrollWidget = QWidget(self.scrollArea)
self.infoPanel = IconInfoPanel(FluentIcon.MENU, self)
self.vBoxLayout = QVBoxLayout(self)
self.hBoxLayout = QHBoxLayout(self.view)
self.flowLayout = FlowLayout(self.scrollWidget)
self.cards = [] # type:List[IconCard]
self.icons = []
self.currentIndex = -1
self.__initWidget()
def __initWidget(self):
self.scrollArea.setWidget(self.scrollWidget)
self.scrollArea.setViewportMargins(0, 5, 0, 5)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.vBoxLayout.setContentsMargins(0, 0, 0, 0)
self.vBoxLayout.setSpacing(12)
self.vBoxLayout.addWidget(self.iconLibraryLabel)
self.vBoxLayout.addWidget(self.searchLineEdit)
self.vBoxLayout.addWidget(self.view)
self.hBoxLayout.setSpacing(0)
self.hBoxLayout.setContentsMargins(0, 0, 0, 0)
self.hBoxLayout.addWidget(self.scrollArea)
self.hBoxLayout.addWidget(self.infoPanel, 0, Qt.AlignRight)
self.flowLayout.setVerticalSpacing(8)
self.flowLayout.setHorizontalSpacing(8)
self.flowLayout.setContentsMargins(8, 3, 8, 8)
self.__setQss()
cfg.themeChanged.connect(self.__setQss)
self.searchLineEdit.clearSignal.connect(self.showAllIcons)
self.searchLineEdit.searchSignal.connect(self.search)
for icon in FluentIcon._member_map_.values():
self.addIcon(icon)
self.setSelectedIcon(self.icons[0])
def addIcon(self, icon: FluentIcon):
""" add icon to view """
card = IconCard(icon, self)
card.clicked.connect(self.setSelectedIcon)
self.trie.insert(icon.value, len(self.cards))
self.cards.append(card)
self.icons.append(icon)
self.flowLayout.addWidget(card)
def setSelectedIcon(self, icon: FluentIcon):
""" set selected icon """
index = self.icons.index(icon)
if self.currentIndex >= 0:
self.cards[self.currentIndex].setSelected(False)
self.currentIndex = index
self.cards[index].setSelected(True)
self.infoPanel.setIcon(icon)
def __setQss(self):
self.view.setObjectName('iconView')
self.scrollWidget.setObjectName('scrollWidget')
self.iconLibraryLabel.setObjectName('iconLibraryLabel')
theme = 'dark' if isDarkTheme() else 'light'
with open(f'app/resource/qss/{theme}/icon_interface.qss', encoding='utf-8') as f:
self.setStyleSheet(applyThemeColor(f.read()))
if self.currentIndex >= 0:
self.cards[self.currentIndex].setSelected(True, True)
def search(self, keyWord: str):
""" search icons """
items = self.trie.items(keyWord.lower())
indexes = {i[1] for i in items}
for i in range(len(self.cards)):
self.cards[i].setVisible(i in indexes)
def showAllIcons(self):
for card in self.cards:
card.show()
class IconInterface(GalleryInterface):
""" Icon interface """
def __init__(self, parent=None):
t = Translator()
super().__init__(
title=t.icons,
subtitle="qfluentwidgets.common.icon",
parent=parent
)
self.iconView = IconCardView(self)
self.vBoxLayout.addWidget(self.iconView)
...@@ -15,6 +15,7 @@ from .home_interface import HomeInterface ...@@ -15,6 +15,7 @@ from .home_interface import HomeInterface
from .basic_input_interface import BasicInputInterface from .basic_input_interface import BasicInputInterface
from .dialog_interface import DialogInterface from .dialog_interface import DialogInterface
from .layout_interface import LayoutInterface from .layout_interface import LayoutInterface
from .icon_interface import IconInterface
from .material_interface import MaterialInterface from .material_interface import MaterialInterface
from .menu_interface import MenuInterface from .menu_interface import MenuInterface
from .scroll_interface import ScrollInterface from .scroll_interface import ScrollInterface
...@@ -71,6 +72,7 @@ class MainWindow(FramelessWindow): ...@@ -71,6 +72,7 @@ class MainWindow(FramelessWindow):
# create sub interface # create sub interface
self.homeInterface = HomeInterface(self) self.homeInterface = HomeInterface(self)
self.iconInterface = IconInterface(self)
self.basicInputInterface = BasicInputInterface(self) self.basicInputInterface = BasicInputInterface(self)
self.dialogInterface = DialogInterface(self) self.dialogInterface = DialogInterface(self)
self.layoutInterface = LayoutInterface(self) self.layoutInterface = LayoutInterface(self)
...@@ -82,6 +84,7 @@ class MainWindow(FramelessWindow): ...@@ -82,6 +84,7 @@ class MainWindow(FramelessWindow):
self.textInterface = TextInterface(self) self.textInterface = TextInterface(self)
self.stackWidget.addWidget(self.homeInterface) self.stackWidget.addWidget(self.homeInterface)
self.stackWidget.addWidget(self.iconInterface)
self.stackWidget.addWidget(self.basicInputInterface) self.stackWidget.addWidget(self.basicInputInterface)
self.stackWidget.addWidget(self.dialogInterface) self.stackWidget.addWidget(self.dialogInterface)
self.stackWidget.addWidget(self.layoutInterface) self.stackWidget.addWidget(self.layoutInterface)
...@@ -118,6 +121,7 @@ class MainWindow(FramelessWindow): ...@@ -118,6 +121,7 @@ class MainWindow(FramelessWindow):
def initNavigation(self): def initNavigation(self):
self.homeInterface.setObjectName('homeInterface') self.homeInterface.setObjectName('homeInterface')
self.iconInterface.setObjectName('iconInterface')
self.basicInputInterface.setObjectName('basicInputInterface') self.basicInputInterface.setObjectName('basicInputInterface')
self.dialogInterface.setObjectName('dialogInterface') self.dialogInterface.setObjectName('dialogInterface')
self.layoutInterface.setObjectName('layoutInterface') self.layoutInterface.setObjectName('layoutInterface')
...@@ -135,6 +139,12 @@ class MainWindow(FramelessWindow): ...@@ -135,6 +139,12 @@ class MainWindow(FramelessWindow):
text=self.tr('Home'), text=self.tr('Home'),
onClick=lambda t: self.switchTo(self.homeInterface, t) onClick=lambda t: self.switchTo(self.homeInterface, t)
) )
self.navigationInterface.addItem(
routeKey=self.iconInterface.objectName(),
icon=Icon.EMOJI_TAB_SYMBOLS,
text=self.tr('Icons'),
onClick=lambda t: self.switchTo(self.iconInterface, t)
)
self.navigationInterface.addSeparator() self.navigationInterface.addSeparator()
self.navigationInterface.addItem( self.navigationInterface.addItem(
......
# coding:utf-8 # coding:utf-8
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap, QColor
from PyQt5.QtWidgets import QWidget, QHBoxLayout
from qfluentwidgets import LineEdit, SpinBox, DoubleSpinBox, TimeEdit, DateTimeEdit, DateEdit, TextEdit from qfluentwidgets import LineEdit, SpinBox, DoubleSpinBox, TimeEdit, DateTimeEdit, DateEdit, TextEdit
from .gallery_interface import GalleryInterface from .gallery_interface import GalleryInterface
......
...@@ -10,6 +10,7 @@ SOURCES += app/view/main_window.py \ ...@@ -10,6 +10,7 @@ SOURCES += app/view/main_window.py \
app/view/material_interface.py \ app/view/material_interface.py \
app/view/layout_interface.py \ app/view/layout_interface.py \
app/view/text_interface.py \ app/view/text_interface.py \
app/view/icon_interface.py \
TRANSLATIONS += app/resource/i18n/gallery_zh.ts \ TRANSLATIONS += app/resource/i18n/gallery_zh.ts \
app/resource/i18n/gallery_hk.ts app/resource/i18n/gallery_hk.ts
...@@ -143,7 +143,7 @@ class SettingInterface(ScrollArea): ...@@ -143,7 +143,7 @@ class SettingInterface(ScrollArea):
) )
self.deskLyricStrokeSizeCard = RangeSettingCard( self.deskLyricStrokeSizeCard = RangeSettingCard(
cfg.deskLyricStrokeSize, cfg.deskLyricStrokeSize,
FIF.FLUORESCENT_PEN, FIF.HIGHTLIGHT,
self.tr('Stroke size'), self.tr('Stroke size'),
parent=self.deskLyricGroup parent=self.deskLyricGroup
) )
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 16 16">
<g> <g>
<path id="path1" transform="rotate(0,8,8) translate(0,0) scale(0.0357142857142857,0.0357142857142857) " fill="#000000" d="M240,32L243.140625,32.2968940734863 246.0625,33.1875267028809 248.765625,34.6718978881836 251.25,36.75 253.328125,39.2343864440918 254.8125,41.9375152587891 255.703125,44.8593864440918 256,48 256,224 432,224 435.140625,224.296875 438.0625,225.1875 440.765625,226.671875 443.25,228.75 445.328125,231.234390258789 446.8125,233.937515258789 447.703125,236.859390258789 448,240 447.703125,243.140625 446.8125,246.0625 445.328125,248.765625 443.25,251.25 440.765625,253.328140258789 438.0625,254.8125 435.140625,255.703125 432,256 256,256 256,432 255.703125,435.140625 254.8125,438.0625 253.328125,440.765625 251.25,443.25 248.765625,445.328125 246.0625,446.8125 243.140625,447.703125 240,448 236.859375,447.703125 233.9375,446.8125 231.234375,445.328125 228.75,443.25 226.671875,440.765625 225.1875,438.0625 224.296875,435.140625 224,432 224,256 48,256 44.859375,255.703125 41.9375,254.8125 39.234375,253.328140258789 36.75,251.25 34.671875,248.765625 33.1875,246.0625 32.296875,243.140625 32,240 32.296875,236.859390258789 33.1875,233.937515258789 34.671875,231.234390258789 36.75,228.75 39.234375,226.671875 41.9375,225.1875 44.859375,224.296875 48,224 224,224 224,48 224.296875,44.8593864440918 225.1875,41.9375152587891 226.671875,39.2343864440918 228.75,36.75 231.234375,34.6718978881836 233.9375,33.1875267028809 236.859375,32.2968940734863 240,32z" /> <path id="path1" transform="rotate(0,8,8) translate(-0.5,-0.5) scale(0.0357142857142857,0.0357142857142857) " fill="#000000" d="M240,32L243.140625,32.2968940734863 246.0625,33.1875267028809 248.765625,34.6718978881836 251.25,36.75 253.328125,39.2343864440918 254.8125,41.9375152587891 255.703125,44.8593864440918 256,48 256,224 432,224 435.140625,224.296875 438.0625,225.1875 440.765625,226.671875 443.25,228.75 445.328125,231.234390258789 446.8125,233.937515258789 447.703125,236.859390258789 448,240 447.703125,243.140625 446.8125,246.0625 445.328125,248.765625 443.25,251.25 440.765625,253.328140258789 438.0625,254.8125 435.140625,255.703125 432,256 256,256 256,432 255.703125,435.140625 254.8125,438.0625 253.328125,440.765625 251.25,443.25 248.765625,445.328125 246.0625,446.8125 243.140625,447.703125 240,448 236.859375,447.703125 233.9375,446.8125 231.234375,445.328125 228.75,443.25 226.671875,440.765625 225.1875,438.0625 224.296875,435.140625 224,432 224,256 48,256 44.859375,255.703125 41.9375,254.8125 39.234375,253.328140258789 36.75,251.25 34.671875,248.765625 33.1875,246.0625 32.296875,243.140625 32,240 32.296875,236.859390258789 33.1875,233.937515258789 34.671875,231.234390258789 36.75,228.75 39.234375,226.671875 41.9375,225.1875 44.859375,224.296875 48,224 224,224 224,48 224.296875,44.8593864440918 225.1875,41.9375152587891 226.671875,39.2343864440918 228.75,36.75 231.234375,34.6718978881836 233.9375,33.1875267028809 236.859375,32.2968940734863 240,32z" />
</g> </g>
</svg> </svg>
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 16 16">
<g> <g>
<path id="path1" transform="rotate(0,8,8) translate(0,0) scale(0.0357142857142857,0.0357142857142857) " fill="#FFFFFF" d="M240,32L243.140625,32.2968940734863 246.0625,33.1875267028809 248.765625,34.6718978881836 251.25,36.75 253.328125,39.2343864440918 254.8125,41.9375152587891 255.703125,44.8593864440918 256,48 256,224 432,224 435.140625,224.296875 438.0625,225.1875 440.765625,226.671875 443.25,228.75 445.328125,231.234390258789 446.8125,233.937515258789 447.703125,236.859390258789 448,240 447.703125,243.140625 446.8125,246.0625 445.328125,248.765625 443.25,251.25 440.765625,253.328140258789 438.0625,254.8125 435.140625,255.703125 432,256 256,256 256,432 255.703125,435.140625 254.8125,438.0625 253.328125,440.765625 251.25,443.25 248.765625,445.328125 246.0625,446.8125 243.140625,447.703125 240,448 236.859375,447.703125 233.9375,446.8125 231.234375,445.328125 228.75,443.25 226.671875,440.765625 225.1875,438.0625 224.296875,435.140625 224,432 224,256 48,256 44.859375,255.703125 41.9375,254.8125 39.234375,253.328140258789 36.75,251.25 34.671875,248.765625 33.1875,246.0625 32.296875,243.140625 32,240 32.296875,236.859390258789 33.1875,233.937515258789 34.671875,231.234390258789 36.75,228.75 39.234375,226.671875 41.9375,225.1875 44.859375,224.296875 48,224 224,224 224,48 224.296875,44.8593864440918 225.1875,41.9375152587891 226.671875,39.2343864440918 228.75,36.75 231.234375,34.6718978881836 233.9375,33.1875267028809 236.859375,32.2968940734863 240,32z" /> <path id="path1" transform="rotate(0,8,8) translate(-0.5,-0.5) scale(0.0357142857142857,0.0357142857142857) " fill="#FFFFFF" d="M240,32L243.140625,32.2968940734863 246.0625,33.1875267028809 248.765625,34.6718978881836 251.25,36.75 253.328125,39.2343864440918 254.8125,41.9375152587891 255.703125,44.8593864440918 256,48 256,224 432,224 435.140625,224.296875 438.0625,225.1875 440.765625,226.671875 443.25,228.75 445.328125,231.234390258789 446.8125,233.937515258789 447.703125,236.859390258789 448,240 447.703125,243.140625 446.8125,246.0625 445.328125,248.765625 443.25,251.25 440.765625,253.328140258789 438.0625,254.8125 435.140625,255.703125 432,256 256,256 256,432 255.703125,435.140625 254.8125,438.0625 253.328125,440.765625 251.25,443.25 248.765625,445.328125 246.0625,446.8125 243.140625,447.703125 240,448 236.859375,447.703125 233.9375,446.8125 231.234375,445.328125 228.75,443.25 226.671875,440.765625 225.1875,438.0625 224.296875,435.140625 224,432 224,256 48,256 44.859375,255.703125 41.9375,254.8125 39.234375,253.328140258789 36.75,251.25 34.671875,248.765625 33.1875,246.0625 32.296875,243.140625 32,240 32.296875,236.859390258789 33.1875,233.937515258789 34.671875,231.234390258789 36.75,228.75 39.234375,226.671875 41.9375,225.1875 44.859375,224.296875 48,224 224,224 224,48 224.296875,44.8593864440918 225.1875,41.9375152587891 226.671875,39.2343864440918 228.75,36.75 231.234375,34.6718978881836 233.9375,33.1875267028809 236.859375,32.2968940734863 240,32z" />
</g> </g>
</svg> </svg>
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<svg id="" width="16" height="16" style="width:16px;height:16px;" version="1.1" <svg id="" width="16" height="16" style="width:16px;height:16px;" version="1.1"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2048 2048" enable-background="new 0 0 2048 2048" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2048 2048" enable-background="new 0 0 2048 2048"
xml:space="preserve"><path fill="#000000" d="M192 2048 q-39 0 -74 -15 q-35 -15 -61.5 -41.5 q-26.5 -26.5 -41.5 -61.5 q-15 -35 -15 -74 l0 -1664 q0 -39 15 -74 q15 -35 41.5 -61.5 q26.5 -26.5 61.5 -41.5 q35 -15 74 -15 l128 0 q39 0 74 15 q35 15 61.5 41.5 q26.5 26.5 41.5 61.5 q15 35 15 74 l0 1664 q0 39 -15 74 q-15 35 -41.5 61.5 q-26.5 26.5 -61.5 41.5 q-35 15 -74 15 l-128 0 ZM832 2048 q-39 0 -74 -15 q-35 -15 -61.5 -41.5 q-26.5 -26.5 -41.5 -61.5 q-15 -35 -15 -74 l0 -1664 q0 -39 15 -74 q15 -35 41.5 -61.5 q26.5 -26.5 61.5 -41.5 q35 -15 74 -15 l128 0 q39 0 74 15 q35 15 61.5 41.5 q26.5 26.5 41.5 61.5 q15 35 15 74 l0 1664 q0 39 -15 74 q-15 35 -41.5 61.5 q-26.5 26.5 -61.5 41.5 q-35 15 -74 15 l-128 0 ZM320 1920 q26 0 45 -19 q19 -19 19 -45 l0 -1664 q0 -26 -19 -45 q-19 -19 -45 -19 l-128 0 q-26 0 -45 19 q-19 19 -19 45 l0 1664 q0 26 19 45 q19 19 45 19 l128 0 ZM960 1920 q26 0 45 -19 q19 -19 19 -45 l0 -1664 q0 -26 -19 -45 q-19 -19 -45 -19 l-128 0 q-26 0 -45 19 q-19 19 -19 45 l0 1664 q0 26 19 45 q19 19 45 19 l128 0 ZM1281 603 q0 -66 38.5 -116 q38.5 -50 101.5 -69 q36 -11 74 -23 q38 -12 76 -12 q33 0 63.5 11.5 q30.5 11.5 55 31.5 q24.5 20 42 47.5 q17.5 27.5 25.5 59.5 l286 1245 q5 23 5 43 q0 67 -39.5 117.5 q-39.5 50.5 -103.5 68.5 q-42 12 -86.5 26 q-44.5 14 -89.5 14 q-34 0 -65 -11.5 q-31 -11.5 -56 -31.5 q-25 -20 -42.5 -48.5 q-17.5 -28.5 -24.5 -61.5 l-256 -1253 q-4 -17 -4 -38 ZM1920 1822 q0 -5 -2 -15 l-286 -1246 q-5 -21 -22.5 -35 q-17.5 -14 -39.5 -14 q-26 0 -57.5 10.5 q-31.5 10.5 -57.5 18.5 q-20 6 -33 23.5 q-13 17.5 -13 38.5 q0 3 0 6.5 q0 3.5 1 6.5 l256 1252 q5 23 22.5 37 q17.5 14 40.5 14 q12 0 31 -4 q19 -4 39.5 -10 q20.5 -6 40 -12 q19.5 -6 32.5 -10 q20 -6 34 -22.5 q14 -16.5 14 -38.5 Z"/></svg> xml:space="preserve"><path fill="#ffffff" d="M192 2048 q-39 0 -74 -15 q-35 -15 -61.5 -41.5 q-26.5 -26.5 -41.5 -61.5 q-15 -35 -15 -74 l0 -1664 q0 -39 15 -74 q15 -35 41.5 -61.5 q26.5 -26.5 61.5 -41.5 q35 -15 74 -15 l128 0 q39 0 74 15 q35 15 61.5 41.5 q26.5 26.5 41.5 61.5 q15 35 15 74 l0 1664 q0 39 -15 74 q-15 35 -41.5 61.5 q-26.5 26.5 -61.5 41.5 q-35 15 -74 15 l-128 0 ZM832 2048 q-39 0 -74 -15 q-35 -15 -61.5 -41.5 q-26.5 -26.5 -41.5 -61.5 q-15 -35 -15 -74 l0 -1664 q0 -39 15 -74 q15 -35 41.5 -61.5 q26.5 -26.5 61.5 -41.5 q35 -15 74 -15 l128 0 q39 0 74 15 q35 15 61.5 41.5 q26.5 26.5 41.5 61.5 q15 35 15 74 l0 1664 q0 39 -15 74 q-15 35 -41.5 61.5 q-26.5 26.5 -61.5 41.5 q-35 15 -74 15 l-128 0 ZM320 1920 q26 0 45 -19 q19 -19 19 -45 l0 -1664 q0 -26 -19 -45 q-19 -19 -45 -19 l-128 0 q-26 0 -45 19 q-19 19 -19 45 l0 1664 q0 26 19 45 q19 19 45 19 l128 0 ZM960 1920 q26 0 45 -19 q19 -19 19 -45 l0 -1664 q0 -26 -19 -45 q-19 -19 -45 -19 l-128 0 q-26 0 -45 19 q-19 19 -19 45 l0 1664 q0 26 19 45 q19 19 45 19 l128 0 ZM1281 603 q0 -66 38.5 -116 q38.5 -50 101.5 -69 q36 -11 74 -23 q38 -12 76 -12 q33 0 63.5 11.5 q30.5 11.5 55 31.5 q24.5 20 42 47.5 q17.5 27.5 25.5 59.5 l286 1245 q5 23 5 43 q0 67 -39.5 117.5 q-39.5 50.5 -103.5 68.5 q-42 12 -86.5 26 q-44.5 14 -89.5 14 q-34 0 -65 -11.5 q-31 -11.5 -56 -31.5 q-25 -20 -42.5 -48.5 q-17.5 -28.5 -24.5 -61.5 l-256 -1253 q-4 -17 -4 -38 ZM1920 1822 q0 -5 -2 -15 l-286 -1246 q-5 -21 -22.5 -35 q-17.5 -14 -39.5 -14 q-26 0 -57.5 10.5 q-31.5 10.5 -57.5 18.5 q-20 6 -33 23.5 q-13 17.5 -13 38.5 q0 3 0 6.5 q0 3.5 1 6.5 l256 1252 q5 23 22.5 37 q17.5 14 40.5 14 q12 0 31 -4 q19 -4 39.5 -10 q20.5 -6 40 -12 q19.5 -6 32.5 -10 q20 -6 34 -22.5 q14 -16.5 14 -38.5 Z"/></svg>
\ No newline at end of file \ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 16 16">
<g> <g>
<path id="path1" transform="rotate(0,8,8) translate(-0.5,0) scale(0.205128205128205,0.205128205128205) " fill="#000000" d="M15,12L16.13671875,12.22265625 17.109375,12.890625 45,40.78125 72.890625,12.890625 73.86328125,12.22265625 75,12 76.13671875,12.22265625 77.109375,12.890625 77.77734375,13.86328125 78,15 77.77734375,16.13671875 77.109375,17.109375 49.21875,45 77.109375,72.890625 77.77734375,73.86328125 78,75 77.77734375,76.13671875 77.109375,77.109375 76.13671875,77.77734375 75,78 73.86328125,77.77734375 72.890625,77.109375 45,49.21875 17.109375,77.109375 16.13671875,77.77734375 15,78 13.8632802963257,77.77734375 12.890625,77.109375 12.22265625,76.13671875 12,75 12.22265625,73.86328125 12.890625,72.890625 40.78125,45 12.890625,17.109375 12.22265625,16.13671875 12,15 12.22265625,13.86328125 12.890625,12.890625 13.8632802963257,12.22265625 15,12z" /> <path id="path1" transform="rotate(0,8,8) translate(-1.5,-1.5) scale(0.205128205128205,0.205128205128205) " fill="#000000" d="M15,12L16.13671875,12.22265625 17.109375,12.890625 45,40.78125 72.890625,12.890625 73.86328125,12.22265625 75,12 76.13671875,12.22265625 77.109375,12.890625 77.77734375,13.86328125 78,15 77.77734375,16.13671875 77.109375,17.109375 49.21875,45 77.109375,72.890625 77.77734375,73.86328125 78,75 77.77734375,76.13671875 77.109375,77.109375 76.13671875,77.77734375 75,78 73.86328125,77.77734375 72.890625,77.109375 45,49.21875 17.109375,77.109375 16.13671875,77.77734375 15,78 13.8632802963257,77.77734375 12.890625,77.109375 12.22265625,76.13671875 12,75 12.22265625,73.86328125 12.890625,72.890625 40.78125,45 12.890625,17.109375 12.22265625,16.13671875 12,15 12.22265625,13.86328125 12.890625,12.890625 13.8632802963257,12.22265625 15,12z" />
</g> </g>
</svg> </svg>
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 16 16">
<g> <g>
<path id="path1" transform="rotate(0,8,8) translate(-0.5,0) scale(0.205128205128205,0.205128205128205) " fill="#FFFFFF" d="M15,12L16.13671875,12.22265625 17.109375,12.890625 45,40.78125 72.890625,12.890625 73.86328125,12.22265625 75,12 76.13671875,12.22265625 77.109375,12.890625 77.77734375,13.86328125 78,15 77.77734375,16.13671875 77.109375,17.109375 49.21875,45 77.109375,72.890625 77.77734375,73.86328125 78,75 77.77734375,76.13671875 77.109375,77.109375 76.13671875,77.77734375 75,78 73.86328125,77.77734375 72.890625,77.109375 45,49.21875 17.109375,77.109375 16.13671875,77.77734375 15,78 13.8632802963257,77.77734375 12.890625,77.109375 12.22265625,76.13671875 12,75 12.22265625,73.86328125 12.890625,72.890625 40.78125,45 12.890625,17.109375 12.22265625,16.13671875 12,15 12.22265625,13.86328125 12.890625,12.890625 13.8632802963257,12.22265625 15,12z" /> <path id="path1" transform="rotate(0,8,8) translate(-1.5,-1.5) scale(0.205128205128205,0.205128205128205) " fill="#FFFFFF" d="M15,12L16.13671875,12.22265625 17.109375,12.890625 45,40.78125 72.890625,12.890625 73.86328125,12.22265625 75,12 76.13671875,12.22265625 77.109375,12.890625 77.77734375,13.86328125 78,15 77.77734375,16.13671875 77.109375,17.109375 49.21875,45 77.109375,72.890625 77.77734375,73.86328125 78,75 77.77734375,76.13671875 77.109375,77.109375 76.13671875,77.77734375 75,78 73.86328125,77.77734375 72.890625,77.109375 45,49.21875 17.109375,77.109375 16.13671875,77.77734375 15,78 13.8632802963257,77.77734375 12.890625,77.109375 12.22265625,76.13671875 12,75 12.22265625,73.86328125 12.890625,72.890625 40.78125,45 12.890625,17.109375 12.22265625,16.13671875 12,15 12.22265625,13.86328125 12.890625,12.890625 13.8632802963257,12.22265625 15,12z" />
</g> </g>
</svg> </svg>
...@@ -34,17 +34,17 @@ LineEdit:disabled, TextEdit:disabled, PlainTextEdit:disabled { ...@@ -34,17 +34,17 @@ LineEdit:disabled, TextEdit:disabled, PlainTextEdit:disabled {
border: 1px solid rgb(73, 73, 73); border: 1px solid rgb(73, 73, 73);
} }
#clearButton { #lineEditButton {
background-color: transparent; background-color: transparent;
border-radius: 4px; border-radius: 4px;
margin: 0; margin: 0;
} }
#clearButton:hover { #lineEditButton:hover {
background-color: rgba(255, 255, 255, 9); background-color: rgba(255, 255, 255, 9);
} }
#clearButton:pressed { #lineEditButton:pressed {
background-color: rgba(255, 255, 255, 6); background-color: rgba(255, 255, 255, 6);
} }
......
...@@ -38,17 +38,17 @@ PlainTextEdit:disabled { ...@@ -38,17 +38,17 @@ PlainTextEdit:disabled {
border: 1px solid rgb(237, 237, 237); border: 1px solid rgb(237, 237, 237);
} }
#clearButton { #lineEditButton {
background-color: transparent; background-color: transparent;
border-radius: 4px; border-radius: 4px;
margin: 0; margin: 0;
} }
#clearButton:hover { #lineEditButton:hover {
background-color: rgba(0, 0, 0, 9); background-color: rgba(0, 0, 0, 9);
} }
#clearButton:pressed { #lineEditButton:pressed {
background-color: rgba(0, 0, 0, 6); background-color: rgba(0, 0, 0, 6);
} }
......
此差异已折叠。
...@@ -35,8 +35,8 @@ ...@@ -35,8 +35,8 @@
<file>images/icons/Embed_white.svg</file> <file>images/icons/Embed_white.svg</file>
<file>images/icons/Feedback_black.svg</file> <file>images/icons/Feedback_black.svg</file>
<file>images/icons/Feedback_white.svg</file> <file>images/icons/Feedback_white.svg</file>
<file>images/icons/FluorescentPen_black.svg</file> <file>images/icons/Highlight_black.svg</file>
<file>images/icons/FluorescentPen_white.svg</file> <file>images/icons/Highlight_white.svg</file>
<file>images/icons/FolderAdd_black.svg</file> <file>images/icons/FolderAdd_black.svg</file>
<file>images/icons/FolderAdd_white.svg</file> <file>images/icons/FolderAdd_white.svg</file>
<file>images/icons/Font_black.svg</file> <file>images/icons/Font_black.svg</file>
......
from .config import * from .config import *
from .auto_wrap import TextWrap from .auto_wrap import TextWrap
from .icon import Icon, getIconColor, drawSvgIcon, FluentIcon, drawIcon, FluentIconBase from .icon import Icon, getIconColor, drawSvgIcon, FluentIcon, drawIcon, FluentIconBase, writeSvg
from .style_sheet import setStyleSheet, getStyleSheet, setTheme, ThemeColor, themeColor, setThemeColor from .style_sheet import setStyleSheet, getStyleSheet, setTheme, ThemeColor, themeColor, setThemeColor, applyThemeColor
from .smooth_scroll import SmoothScroll, SmoothMode from .smooth_scroll import SmoothScroll, SmoothMode
\ No newline at end of file
...@@ -245,15 +245,15 @@ class FluentIcon(FluentIconBase, Enum): ...@@ -245,15 +245,15 @@ class FluentIcon(FluentIconBase, Enum):
CONSTRACT = "Constract" CONSTRACT = "Constract"
ALIGNMENT = "Alignment" ALIGNMENT = "Alignment"
BOOK_SHELF = "BookShelf" BOOK_SHELF = "BookShelf"
PENCIL_INK = "PencilInk" HIGHTLIGHT = "Highlight"
FOLDER_ADD = "FolderAdd" FOLDER_ADD = "FolderAdd"
PENCIL_INK = "PencilInk"
MICROPHONE = "Microphone" MICROPHONE = "Microphone"
ARROW_DOWN = "ChevronDown" ARROW_DOWN = "ChevronDown"
TRANSPARENT = "Transparent" TRANSPARENT = "Transparent"
MUSIC_FOLDER = "MusicFolder" MUSIC_FOLDER = "MusicFolder"
CHEVRON_RIGHT = "ChevronRight" CHEVRON_RIGHT = "ChevronRight"
BACKGROUND_FILL = "BackgroundColor" BACKGROUND_FILL = "BackgroundColor"
FLUORESCENT_PEN = "FluorescentPen"
def path(self, theme=Theme.AUTO): def path(self, theme=Theme.AUTO):
if theme == Theme.AUTO: if theme == Theme.AUTO:
......
# coding:utf-8 # coding:utf-8
from collections import deque from collections import deque
from enum import Enum from enum import Enum
from math import cos, pi from math import cos, pi, ceil
from PyQt5.QtCore import QDateTime, Qt, QTimer, QPoint from PyQt5.QtCore import QDateTime, Qt, QTimer, QPoint
from PyQt5.QtGui import QWheelEvent from PyQt5.QtGui import QWheelEvent
......
...@@ -52,6 +52,20 @@ class QssTemplate(Template): ...@@ -52,6 +52,20 @@ class QssTemplate(Template):
delimiter = '--' delimiter = '--'
def applyThemeColor(qss: str):
""" apply theme color to style sheet
Parameters
----------
qss: str
the style sheet string to apply theme color, the substituted variable
should be equal to the value of `ThemeColor` and starts width `--`, i.e `--ThemeColorPrimary`
"""
template = QssTemplate(qss)
mappings = {c.value: c.name() for c in ThemeColor._member_map_.values()}
return template.safe_substitute(mappings)
def getStyleSheet(file, theme=Theme.AUTO): def getStyleSheet(file, theme=Theme.AUTO):
""" get style sheet from `qfluentwidgets` embedded qss file """ get style sheet from `qfluentwidgets` embedded qss file
...@@ -66,11 +80,10 @@ def getStyleSheet(file, theme=Theme.AUTO): ...@@ -66,11 +80,10 @@ def getStyleSheet(file, theme=Theme.AUTO):
theme = qconfig.theme if theme == Theme.AUTO else theme theme = qconfig.theme if theme == Theme.AUTO else theme
f = QFile(f":/qfluentwidgets/qss/{theme.value.lower()}/{file}.qss") f = QFile(f":/qfluentwidgets/qss/{theme.value.lower()}/{file}.qss")
f.open(QFile.ReadOnly) f.open(QFile.ReadOnly)
template = QssTemplate(str(f.readAll(), encoding='utf-8')) qss = str(f.readAll(), encoding='utf-8')
f.close() f.close()
mappings = {c.value: c.name() for c in ThemeColor._member_map_.values()} return applyThemeColor(qss)
return template.safe_substitute(mappings)
def setStyleSheet(widget, file, theme=Theme.AUTO, register=True): def setStyleSheet(widget, file, theme=Theme.AUTO, register=True):
......
# coding:utf-8 # coding:utf-8
from typing import List
from PyQt5.QtCore import QSize, QPoint, Qt, QRect, QPropertyAnimation, QParallelAnimationGroup, QEasingCurve from PyQt5.QtCore import QSize, QPoint, Qt, QRect, QPropertyAnimation, QParallelAnimationGroup, QEasingCurve
from PyQt5.QtWidgets import QLayout, QWidgetItem from PyQt5.QtWidgets import QLayout, QWidgetItem, QLayoutItem
class FlowLayout(QLayout): class FlowLayout(QLayout):
...@@ -17,7 +19,7 @@ class FlowLayout(QLayout): ...@@ -17,7 +19,7 @@ class FlowLayout(QLayout):
whether to add moving animation whether to add moving animation
""" """
super().__init__(parent) super().__init__(parent)
self._items = [] self._items = [] # type: List[QLayoutItem]
self._anis = [] self._anis = []
self._aniGroup = QParallelAnimationGroup(self) self._aniGroup = QParallelAnimationGroup(self)
self._verticalSpacing = 10 self._verticalSpacing = 10
...@@ -33,6 +35,7 @@ class FlowLayout(QLayout): ...@@ -33,6 +35,7 @@ class FlowLayout(QLayout):
return return
ani = QPropertyAnimation(w, b'geometry') ani = QPropertyAnimation(w, b'geometry')
ani.setEndValue(QRect(QPoint(0, 0), w.size()))
ani.setDuration(300) ani.setDuration(300)
w.setProperty('flowAni', ani) w.setProperty('flowAni', ani)
self._anis.append(ani) self._anis.append(ani)
...@@ -98,11 +101,11 @@ class FlowLayout(QLayout): ...@@ -98,11 +101,11 @@ class FlowLayout(QLayout):
def heightForWidth(self, width: int): def heightForWidth(self, width: int):
""" get the minimal height according to width """ """ get the minimal height according to width """
return self.__doLayout(QRect(0, 0, width, 0), False) return self._doLayout(QRect(0, 0, width, 0), False)
def setGeometry(self, rect: QRect): def setGeometry(self, rect: QRect):
super().setGeometry(rect) super().setGeometry(rect)
self.__doLayout(rect, True) self._doLayout(rect, True)
def sizeHint(self): def sizeHint(self):
return self.minimumSize() return self.minimumSize()
...@@ -134,7 +137,7 @@ class FlowLayout(QLayout): ...@@ -134,7 +137,7 @@ class FlowLayout(QLayout):
""" get horizontal spacing between widgets """ """ get horizontal spacing between widgets """
return self._horizontalSpacing return self._horizontalSpacing
def __doLayout(self, rect: QRect, move: bool): def _doLayout(self, rect: QRect, move: bool):
""" adjust widgets position according to the window size """ """ adjust widgets position according to the window size """
margin = self.contentsMargins() margin = self.contentsMargins()
x = rect.x() + margin.left() x = rect.x() + margin.left()
...@@ -144,6 +147,9 @@ class FlowLayout(QLayout): ...@@ -144,6 +147,9 @@ class FlowLayout(QLayout):
spaceY = self.verticalSpacing() spaceY = self.verticalSpacing()
for i, item in enumerate(self._items): for i, item in enumerate(self._items):
if item.widget() and not item.widget().isVisible() and not self.needAni:
continue
nextX = x + item.sizeHint().width() + spaceX nextX = x + item.sizeHint().width() + spaceX
if nextX - spaceX > rect.right() and rowHeight > 0: if nextX - spaceX > rect.right() and rowHeight > 0:
......
...@@ -40,7 +40,7 @@ class ToolButton(QToolButton): ...@@ -40,7 +40,7 @@ class ToolButton(QToolButton):
painter.setOpacity(0.63 if self.isPressed else 1) painter.setOpacity(0.63 if self.isPressed else 1)
w, h = self._iconSize w, h = self._iconSize
drawIcon(self._icon, painter, QRectF( drawIcon(self._icon, painter, QRectF(
(self.width()-w)//2, (self.height()-h)//2, w, h)) (self.width()-w)/2, (self.height()-h)/2, w, h))
class PushButton(QPushButton): class PushButton(QPushButton):
......
from .button import PrimaryPushButton, PushButton, RadioButton, HyperlinkButton, ToolButton from .button import PrimaryPushButton, PushButton, RadioButton, HyperlinkButton, ToolButton
from .check_box import CheckBox from .check_box import CheckBox
from .combo_box import ComboBox from .combo_box import ComboBox
from .line_edit import LineEdit, TextEdit, PlainTextEdit from .line_edit import LineEdit, TextEdit, PlainTextEdit, LineEditButton, SearchLineEdit
from .icon_widget import IconWidget from .icon_widget import IconWidget
from .label import PixmapLabel from .label import PixmapLabel
from .menu import DWMMenu, LineEditMenu, RoundMenu from .menu import DWMMenu, LineEditMenu, RoundMenu
......
...@@ -14,6 +14,10 @@ class IconWidget(QWidget): ...@@ -14,6 +14,10 @@ class IconWidget(QWidget):
super().__init__(parent=parent) super().__init__(parent=parent)
self.icon = icon self.icon = icon
def setIcon(self, icon: Union[str, QIcon, FluentIconBase]):
self.icon = icon
self.update()
def paintEvent(self, e): def paintEvent(self, e):
painter = QPainter(self) painter = QPainter(self)
painter.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) painter.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
......
...@@ -31,7 +31,7 @@ class InfoBarCloseButton(QToolButton): ...@@ -31,7 +31,7 @@ class InfoBarCloseButton(QToolButton):
painter = QPainter(self) painter = QPainter(self)
painter.setRenderHints(QPainter.Antialiasing | painter.setRenderHints(QPainter.Antialiasing |
QPainter.SmoothPixmapTransform) QPainter.SmoothPixmapTransform)
FIF.CLOSE.render(painter, QRectF(11, 12, 12, 12)) FIF.CLOSE.render(painter, QRectF(12, 12, 12, 12))
class InfoBarIcon(FluentIconBase, Enum): class InfoBarIcon(FluentIconBase, Enum):
......
# coding: utf-8 # coding: utf-8
from PyQt5.QtCore import QSize, Qt, QRectF, QEvent from typing import Union
from PyQt5.QtGui import QPainter, QPainterPath from PyQt5.QtCore import QSize, Qt, QRectF, pyqtSignal
from PyQt5.QtWidgets import QLineEdit, QToolButton, QTextEdit, QPlainTextEdit from PyQt5.QtGui import QPainter, QPainterPath, QIcon
from PyQt5.QtWidgets import QHBoxLayout, QLineEdit, QToolButton, QTextEdit, QPlainTextEdit
from ...common.style_sheet import setStyleSheet, themeColor from ...common.style_sheet import setStyleSheet, themeColor
from ...common.icon import writeSvg, isDarkTheme, drawSvgIcon from ...common.icon import writeSvg, isDarkTheme, drawSvgIcon, FluentIconBase
from ...common.icon import FluentIcon as FIF from ...common.icon import FluentIcon as FIF
from ...common.smooth_scroll import SmoothMode, SmoothScroll from ...common.smooth_scroll import SmoothMode, SmoothScroll
from .menu import LineEditMenu, TextEditMenu from .menu import LineEditMenu, TextEditMenu
class ClearButton(QToolButton): class LineEditButton(QToolButton):
""" Clear button """ """ Line edit button """
def __init__(self, parent=None): def __init__(self, icon: Union[str, QIcon, FluentIconBase], parent=None):
super().__init__(parent=parent) super().__init__(parent=parent)
self.setFixedSize(29, 25) self._icon = icon
self.setFixedSize(31, 23)
self.setIconSize(QSize(10, 10)) self.setIconSize(QSize(10, 10))
self.setCursor(Qt.PointingHandCursor) self.setCursor(Qt.PointingHandCursor)
self.setObjectName('clearButton') self.setObjectName('lineEditButton')
setStyleSheet(self, 'line_edit') setStyleSheet(self, 'line_edit')
def paintEvent(self, e): def paintEvent(self, e):
...@@ -26,11 +28,16 @@ class ClearButton(QToolButton): ...@@ -26,11 +28,16 @@ class ClearButton(QToolButton):
painter = QPainter(self) painter = QPainter(self)
painter.setRenderHints(QPainter.Antialiasing | painter.setRenderHints(QPainter.Antialiasing |
QPainter.SmoothPixmapTransform) QPainter.SmoothPixmapTransform)
iw, ih = self.iconSize().width(), self.iconSize().height()
w, h = self.width(), self.height()
rect = QRectF((w - iw)/2, (h - ih)/2, iw, ih)
if isDarkTheme(): if isDarkTheme():
FIF.CLOSE.render(painter, QRectF(9.5, 7, 10, 10)) self._icon.render(painter, rect)
else: else:
svg = writeSvg(FIF.CLOSE.path(), fill='#656565') svg = writeSvg(self._icon.path(), fill='#656565')
drawSvgIcon(svg.encode(), painter, QRectF(9.5, 7, 10, 10)) drawSvgIcon(svg.encode(), painter, rect)
class LineEdit(QLineEdit): class LineEdit(QLineEdit):
...@@ -44,10 +51,17 @@ class LineEdit(QLineEdit): ...@@ -44,10 +51,17 @@ class LineEdit(QLineEdit):
self.setFixedHeight(33) self.setFixedHeight(33)
self.setAttribute(Qt.WA_MacShowFocusRect, False) self.setAttribute(Qt.WA_MacShowFocusRect, False)
self.clearButton = ClearButton(self) self.hBoxLayout = QHBoxLayout(self)
self.clearButton.move(self.width() - 33, 4) self.clearButton = LineEditButton(FIF.CLOSE, self)
self.clearButton.setFixedSize(29, 25)
self.clearButton.hide() self.clearButton.hide()
self.hBoxLayout.setSpacing(3)
self.hBoxLayout.setContentsMargins(4, 4, 4, 4)
self.hBoxLayout.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
self.hBoxLayout.addWidget(self.clearButton, 0, Qt.AlignRight)
self.clearButton.clicked.connect(self.clear) self.clearButton.clicked.connect(self.clear)
self.textChanged.connect(self.__onTextChanged) self.textChanged.connect(self.__onTextChanged)
...@@ -76,9 +90,6 @@ class LineEdit(QLineEdit): ...@@ -76,9 +90,6 @@ class LineEdit(QLineEdit):
menu = LineEditMenu(self) menu = LineEditMenu(self)
menu.exec_(e.globalPos()) menu.exec_(e.globalPos())
def resizeEvent(self, e):
self.clearButton.move(self.width() - 33, 4)
def paintEvent(self, e): def paintEvent(self, e):
super().paintEvent(e) super().paintEvent(e)
if not self.hasFocus(): if not self.hasFocus():
...@@ -99,6 +110,32 @@ class LineEdit(QLineEdit): ...@@ -99,6 +110,32 @@ class LineEdit(QLineEdit):
painter.fillPath(path, themeColor()) painter.fillPath(path, themeColor())
class SearchLineEdit(LineEdit):
""" Search line edit """
searchSignal = pyqtSignal(str)
clearSignal = pyqtSignal()
def __init__(self, parent=None):
super().__init__('', parent)
self.searchButton = LineEditButton(FIF.SEARCH, self)
self.hBoxLayout.addWidget(self.searchButton, 0, Qt.AlignRight)
self.setClearButtonEnabled(True)
self.setTextMargins(0, 0, 59, 0)
self.searchButton.clicked.connect(self.search)
self.clearButton.clicked.connect(self.clearSignal)
def search(self, text: str):
""" emit search signal """
text = text.strip()
if text:
self.searchSignal.emit(text)
else:
self.clearSignal.emit()
class TextEdit(QTextEdit): class TextEdit(QTextEdit):
""" Text edit """ """ Text edit """
...@@ -137,4 +174,3 @@ class PlainTextEdit(QPlainTextEdit): ...@@ -137,4 +174,3 @@ class PlainTextEdit(QPlainTextEdit):
self.verticalSmoothScroll.wheelEvent(e) self.verticalSmoothScroll.wheelEvent(e)
else: else:
self.horizonSmoothScroll.wheelEvent(e) self.horizonSmoothScroll.wheelEvent(e)
# coding:utf-8 # coding:utf-8
from PyQt5.QtCore import QEasingCurve, Qt, pyqtSignal, QPropertyAnimation, QEvent from PyQt5.QtCore import QEasingCurve, Qt, pyqtSignal, QPropertyAnimation, QEvent
from PyQt5.QtGui import QWheelEvent, QKeyEvent
from PyQt5.QtWidgets import QScrollArea, QScrollBar from PyQt5.QtWidgets import QScrollArea, QScrollBar
from ...common.smooth_scroll import SmoothScroll, SmoothMode from ...common.smooth_scroll import SmoothScroll, SmoothMode
...@@ -20,7 +21,6 @@ class ScrollArea(QScrollArea): ...@@ -20,7 +21,6 @@ class ScrollArea(QScrollArea):
""" """
super().__init__(parent) super().__init__(parent)
self.smoothScroll = SmoothScroll(self, orient) self.smoothScroll = SmoothScroll(self, orient)
self.viewport().installEventFilter(self)
def setSmoothMode(self, mode): def setSmoothMode(self, mode):
""" set smooth mode """ set smooth mode
...@@ -32,33 +32,24 @@ class ScrollArea(QScrollArea): ...@@ -32,33 +32,24 @@ class ScrollArea(QScrollArea):
""" """
self.smoothScroll.setSmoothMode(mode) self.smoothScroll.setSmoothMode(mode)
def eventFilter(self, obj, e): def wheelEvent(self, e: QWheelEvent):
if obj is self.viewport(): self.smoothScroll.wheelEvent(e)
if e.type() == QEvent.Wheel: e.setAccepted(True)
self.smoothScroll.wheelEvent(e)
# stop event propagation
e.setAccepted(True)
return True
return super().eventFilter(obj, e)
class SmoothScrollBar(QScrollBar): class SmoothScrollBar(QScrollBar):
""" Smooth scroll bar """ """ Smooth scroll bar """
scrollFinished = pyqtSignal()
def __init__(self, parent=None): def __init__(self, parent=None):
QScrollBar.__init__(self, parent) QScrollBar.__init__(self, parent)
self.duration = 500
self.ani = QPropertyAnimation() self.ani = QPropertyAnimation()
self.ani.setTargetObject(self) self.ani.setTargetObject(self)
self.ani.setPropertyName(b"value") self.ani.setPropertyName(b"value")
self.ani.setEasingCurve(QEasingCurve.OutCubic) self.ani.setEasingCurve(QEasingCurve.OutCubic)
self.ani.setDuration(500) self.ani.setDuration(self.duration)
self.__value = self.value() self.__value = self.value()
self.ani.finished.connect(self.scrollFinished)
def setValue(self, value): def setValue(self, value):
if value == self.value(): if value == self.value():
...@@ -66,7 +57,13 @@ class SmoothScrollBar(QScrollBar): ...@@ -66,7 +57,13 @@ class SmoothScrollBar(QScrollBar):
# stop running animation # stop running animation
self.ani.stop() self.ani.stop()
self.scrollFinished.emit()
# adjust the duration
dv = abs(value - self.value())
if dv < 50:
self.ani.setDuration(self.duration * dv / 70)
else:
self.ani.setDuration(self.duration)
self.ani.setStartValue(self.value()) self.ani.setStartValue(self.value())
self.ani.setEndValue(value) self.ani.setEndValue(value)
...@@ -104,6 +101,21 @@ class SmoothScrollBar(QScrollBar): ...@@ -104,6 +101,21 @@ class SmoothScrollBar(QScrollBar):
super().mouseMoveEvent(e) super().mouseMoveEvent(e)
self.__value = self.value() self.__value = self.value()
def setScrollAnimation(self, duration, easing=QEasingCurve.OutCubic):
""" set scroll animation
Parameters
----------
duration: int
scroll duration
easing: QEasingCurve
animation type
"""
self.duration = duration
self.ani.setDuration(duration)
self.ani.setEasingCurve(easing)
class SmoothScrollArea(QScrollArea): class SmoothScrollArea(QScrollArea):
""" Smooth scroll area """ """ Smooth scroll area """
...@@ -132,8 +144,7 @@ class SmoothScrollArea(QScrollArea): ...@@ -132,8 +144,7 @@ class SmoothScrollArea(QScrollArea):
animation type animation type
""" """
bar = self.hScrollBar if orient == Qt.Horizontal else self.vScrollBar bar = self.hScrollBar if orient == Qt.Horizontal else self.vScrollBar
bar.ani.setDuration(duration) bar.setScrollAnimation(duration, easing)
bar.ani.setEasingCurve(easing)
def wheelEvent(self, e): def wheelEvent(self, e):
if e.modifiers() == Qt.NoModifier: if e.modifiers() == Qt.NoModifier:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册