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

添加基本输入的 gallery 界面

上级 f90b063e
......@@ -58,5 +58,5 @@
### Material
### Acrylic Label
#### Acrylic Label
<img width="60%" src="./_static/gallery/acrylic_label.png"/>
\ No newline at end of file
# coding:utf-8
from enum import Enum
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QGuiApplication, QFont
from qfluentwidgets import (qconfig, QConfig, ConfigItem, OptionsConfigItem, BoolValidator,
ColorConfigItem, OptionsValidator, RangeConfigItem, RangeValidator,
FolderListValidator, EnumSerializer, FolderValidator)
class Language(Enum):
""" Language enumeration """
CHINESE_SIMPLIFIED = "zh"
CHINESE_TRADITIONAL = "hk"
ENGLISH = "en"
AUTO = "Auto"
class Config(QConfig):
""" Config of application """
# folders
musicFolders = ConfigItem(
"Folders", "LocalMusic", [], FolderListValidator())
downloadFolder = ConfigItem(
"Folders", "Download", "app/download", FolderValidator())
# main window
minimizeToTray = ConfigItem(
"MainWindow", "MinimizeToTray", True, BoolValidator())
playBarColor = ColorConfigItem("MainWindow", "PlayBarColor", "#225C7F")
recentPlaysNumber = RangeConfigItem(
"MainWindow", "RecentPlayNumbers", 300, RangeValidator(10, 300))
dpiScale = OptionsConfigItem(
"MainWindow", "DpiScale", "Auto", OptionsValidator([1, 1.25, 1.5, 1.75, 2, "Auto"]), restart=True)
language = OptionsConfigItem(
"MainWindow", "Language", Language.AUTO, OptionsValidator(Language), EnumSerializer(Language), restart=True)
# software update
checkUpdateAtStartUp = ConfigItem(
"Update", "CheckUpdateAtStartUp", True, BoolValidator())
YEAR = 2023
AUTHOR = "zhiyiYo"
VERSION = "v0.4.2"
HELP_URL = "https://pyqt-fluent-widgets.readthedocs.io"
EXAMPLE_URL = "https://github.com/zhiyiYo/PyQt-Fluent-Widgets/tree/master/examples"
DOCUMENT_URL = "https://github.com/zhiyiYo/PyQt-Fluent-Widgets/issues"
FEEDBACK_URL = "https://github.com/zhiyiYo/PyQt-Fluent-Widgets/issues"
RELEASE_URL = "https://github.com/zhiyiYo/PyQt-Fluent-Widgets/releases/latest"
cfg = Config()
qconfig.load('app/config/config.json', cfg)
\ No newline at end of file
# coding: utf-8
from enum import Enum
from qfluentwidgets import FluentIconBase, getIconColor, Theme
class Icon(FluentIconBase, Enum):
HOME = "Home"
CHAT = "Chat"
MENU = "Menu"
LAYOUT = "Layout"
GITHUB = "Github"
MESSAGE = "Message"
CHECKBOX = "CheckBox"
DOCUMENT = "Document"
CONSTRACT = "Constract"
def path(self, theme=Theme.AUTO):
if theme == Theme.AUTO:
c = getIconColor()
else:
c = "white" if theme == Theme.DARK else "black"
return f"app/resource/images/icons/{self.value}_{c}.svg"
# coding: utf-8
from PyQt5.QtCore import QObject
class Translator(QObject):
def __init__(self, parent=None):
super().__init__(parent=parent)
self.basicInput = self.tr('Basic input')
self.menus = self.tr('Menus')
self.dialogs = self.tr('Dialogs')
self.material = self.tr('Material')
self.statusInfo = self.tr('Status & info')
self.layout = self.tr('Layout')
\ No newline at end of file
# coding: utf-8
from PyQt5.QtCore import Qt, QRect
from PyQt5.QtGui import QPainter, QImage, QBrush, QColor, QFont
from qfluentwidgets import NavigationWidget, isDarkTheme
class AvatarWidget(NavigationWidget):
""" Avatar widget """
def __init__(self, image_path, parent=None):
super().__init__(isSelectable=False, parent=parent)
self.avatar = QImage(image_path).scaled(
24, 24, Qt.KeepAspectRatio, Qt.SmoothTransformation)
def paintEvent(self, e):
painter = QPainter(self)
painter.setRenderHints(
QPainter.SmoothPixmapTransform | QPainter.Antialiasing)
painter.setPen(Qt.NoPen)
if self.isPressed:
painter.setOpacity(0.7)
# draw background
if self.isEnter:
c = 255 if isDarkTheme() else 0
painter.setBrush(QColor(c, c, c, 10))
painter.drawRoundedRect(self.rect(), 5, 5)
# draw avatar
painter.setBrush(QBrush(self.avatar))
painter.translate(8, 6)
painter.drawEllipse(0, 0, 24, 24)
painter.translate(-8, -6)
if not self.isCompacted:
painter.setPen(Qt.white if isDarkTheme() else Qt.black)
font = QFont('Segoe UI')
font.setPixelSize(14)
painter.setFont(font)
painter.drawText(QRect(44, 0, 255, 36), Qt.AlignVCenter, 'zhiyiYo')
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="zh_CN">
<!-- The translation of components in PyQt-Fluent-Widgets -->
<context>
<name>ColorDialog</name>
<message>
<source>OK</source>
<translation>確認</translation>
</message>
<message>
<source>Cancel</source>
<translation>取消</translation>
</message>
<message>
<source>Edit Color</source>
<translation>編輯顏色</translation>
</message>
<message>
<source>Red</source>
<translation>紅色</translation>
</message>
<message>
<source>Blue</source>
<translation>藍色</translation>
</message>
<message>
<source>Green</source>
<translation>綠色</translation>
</message>
</context>
<context>
<name>MessageDialog</name>
<message>
<source>OK</source>
<translation>確認</translation>
</message>
<message>
<source>Cancel</source>
<translation>取消</translation>
</message>
</context>
<context>
<name>Dialog</name>
<message>
<source>OK</source>
<translation>確認</translation>
</message>
<message>
<source>Cancel</source>
<translation>取消</translation>
</message>
</context>
<context>
<name>FolderListDialog</name>
<message>
<source>Done</source>
<translation>完成</translation>
</message>
<message>
<source>Choose folder</source>
<translation>選擇文件夾</translation>
</message>
<message>
<source>Are you sure you want to delete the folder?</source>
<translation>是否確認刪除此文件夾</translation>
</message>
<message>
<source>If you delete the </source>
<translation>如果將 </translation>
</message>
<message>
<source> folder and remove it from the list, the folder will no longer appear in the
list, but will not be deleted.</source>
<translation> 文件夾從列表中移除則該文件夾不會再出現在列表中但不會被刪除</translation>
</message>
</context>
<context>
<name>SwitchSettingCard</name>
<message>
<source>Off</source>
<translation></translation>
</message>
<message>
<source>On</source>
<translation></translation>
</message>
</context>
<context>
<name>CustomColorSettingCard</name>
<message>
<source>Custom color</source>
<translation>自定義顏色</translation>
</message>
<message>
<source>Default color</source>
<translation>默認顏色</translation>
</message>
<message>
<source>Choose color</source>
<translation>選擇顏色</translation>
</message>
</context>
<context>
<name>ColorPickerButton</name>
<message>
<source>Choose </source>
<translation>選擇</translation>
</message>
</context>
<context>
<name>FolderListSettingCard</name>
<message>
<source>Add folder</source>
<translation>添加文件夾</translation>
</message>
<message>
<source>Choose folder</source>
<translation>選擇文件夾</translation>
</message>
<message>
<source>Are you sure you want to delete the folder?</source>
<translation>是否確認刪除此文件夾</translation>
</message>
<message>
<source>If you delete the </source>
<translation>如果將 </translation>
</message>
<message>
<source> folder and remove it from the list, the folder will no longer appear in the
list, but will not be deleted.</source>
<translation> 文件夾從列表中移除則該文件夾不會再出現在列表中但不會被刪除</translation>
</message>
</context>
<!-- Put the translation of your interface below -->
<context>
<name>SettingInterface</name>
<message>
<source>Settings</source>
<translation>設置</translation>
</message>
<message>
<source>Music on this PC</source>
<translation> PC 上的音樂</translation>
</message>
<message>
<source>Local music library</source>
<translation>本地音樂庫</translation>
</message>
<message>
<source>Choose folder</source>
<translation>選擇文件夾</translation>
</message>
<message>
<source>Download directory</source>
<translation>下載目錄</translation>
</message>
<message>
<source>Personalization</source>
<translation>個性化</translation>
</message>
<message>
<source>Use Acrylic effect</source>
<translation>啟用亞克力效果</translation>
</message>
<message>
<source>Acrylic effect has better visual experience, but it may cause the window to
become stuck</source>
<translation>亞克力效果的視覺體驗更好但可能導致窗口卡頓</translation>
</message>
<message>
<source>Application theme</source>
<translation>應用主題</translation>
</message>
<message>
<source>Theme color</source>
<translation>主題色</translation>
</message>
<message>
<source>Change the theme color of you application</source>
<translation>調整你的應用主題顏色</translation>
</message>
<message>
<source>Change the appearance of your application</source>
<translation>調整你的應用外觀</translation>
</message>
<message>
<source>Light</source>
<translation>淺色</translation>
</message>
<message>
<source>Dark</source>
<translation>深色</translation>
</message>
<message>
<source>Use system setting</source>
<translation>跟隨系統設置</translation>
</message>
<message>
<source>Interface zoom</source>
<translation>界面縮放</translation>
</message>
<message>
<source>Change the size of widgets and fonts</source>
<translation>調整組件和字體的大小</translation>
</message>
<message>
<source>Language</source>
<translation>語言</translation>
</message>
<message>
<source>Set your preferred language for UI</source>
<translation>選擇界面所使用的語言</translation>
</message>
<message>
<source>Online Music</source>
<translation>在線音樂</translation>
</message>
<message>
<source>Number of online music displayed on each page</source>
<translation>每頁顯示的在線歌曲數量</translation>
</message>
<message>
<source>Online music quality</source>
<translation>在線播放音質</translation>
</message>
<message>
<source>Standard quality</source>
<translation>流暢</translation>
</message>
<message>
<source>High quality</source>
<translation>高品</translation>
</message>
<message>
<source>Super quality</source>
<translation>超品</translation>
</message>
<message>
<source>Lossless quality</source>
<translation>無損</translation>
</message>
<message>
<source>Online MV quality</source>
<translation>在線 MV 畫質</translation>
</message>
<message>
<source>Full HD</source>
<translation>超清</translation>
</message>
<message>
<source>HD</source>
<translation>高清</translation>
</message>
<message>
<source>SD</source>
<translation>標清</translation>
</message>
<message>
<source>LD</source>
<translation>流暢</translation>
</message>
<message>
<source>Desktop Lyric</source>
<translation>桌面歌詞</translation>
</message>
<message>
<source>Choose font</source>
<translation>選擇字體</translation>
</message>
<message>
<source>Font</source>
<translation>字體</translation>
</message>
<message>
<source>Foreground color</source>
<translation>前景色</translation>
</message>
<message>
<source>Background color</source>
<translation>背景色</translation>
</message>
<message>
<source>Stroke color</source>
<translation>描邊色</translation>
</message>
<message>
<source>Stroke size</source>
<translation>描邊大小</translation>
</message>
<message>
<source>Alignment</source>
<translation>對齊方式</translation>
</message>
<message>
<source>Center aligned</source>
<translation>居中對齊</translation>
</message>
<message>
<source>Left aligned</source>
<translation>左對齊</translation>
</message>
<message>
<source>Right aligned</source>
<translation>右對齊</translation>
</message>
<message>
<source>Main Panel</source>
<translation>主面板</translation>
</message>
<message>
<source>Minimize to tray after closing</source>
<translation>關閉後最小化到托盤</translation>
</message>
<message>
<source>PyQt-Fluent-Widgets will continue to run in the background</source>
<translation>PyQt-Fluent-Widgets 將在後臺繼續運行</translation>
</message>
<message>
<location filename="../../View/setting_interface/setting_interface.py" line="156" />
<source>Software update</source>
<translation>軟件更新</translation>
</message>
<message>
<source>Check for updates when the application starts</source>
<translation>在應用程序啟動時檢查更新</translation>
</message>
<message>
<source>The new version will be more stable and have more features</source>
<translation>新版本將更加穩定並擁有更多功能建議啟用此選項</translation>
</message>
<message>
<source>About</source>
<translation>關於</translation>
</message>
<message>
<source>Open help page</source>
<translation>打開幫助頁面</translation>
</message>
<message>
<source>Discover new features and learn useful tips about PyQt-Fluent-Widgets</source>
<translation>發現新功能並了解有關 PyQt-Fluent-Widgets 的使用技巧</translation>
</message>
<message>
<source>Provide feedback</source>
<translation>提供反饋</translation>
</message>
<message>
<source>Help us improve PyQt-Fluent-Widgets by providing feedback</source>
<translation>通過提供反饋幫助我們改進 PyQt-Fluent-Widgets</translation>
</message>
<message>
<source>Check update</source>
<translation>檢查更新</translation>
</message>
<message>
<source>Copyright</source>
<translation>版權所有</translation>
</message>
<message>
<source>Version</source>
<translation>當前版本</translation>
</message>
<message>
<source>Configuration updated successfully</source>
<translation>配置更新成功</translation>
</message>
<message>
<source>Configuration takes effect after restart</source>
<translation>配置在重啟軟件後生效</translation>
</message>
</context>
</TS>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="zh_CN">
<!-- The translation of components in PyQt-Fluent-Widgets -->
<context>
<name>ColorDialog</name>
<message>
<source>OK</source>
<translation>确认</translation>
</message>
<message>
<source>Cancel</source>
<translation>取消</translation>
</message>
<message>
<source>Edit Color</source>
<translation>编辑颜色</translation>
</message>
<message>
<source>Red</source>
<translation>红色</translation>
</message>
<message>
<source>Blue</source>
<translation>蓝色</translation>
</message>
<message>
<source>Green</source>
<translation>绿色</translation>
</message>
</context>
<context>
<name>MessageDialog</name>
<message>
<source>OK</source>
<translation>确认</translation>
</message>
<message>
<source>Cancel</source>
<translation>取消</translation>
</message>
</context>
<context>
<name>Dialog</name>
<message>
<source>OK</source>
<translation>确认</translation>
</message>
<message>
<source>Cancel</source>
<translation>取消</translation>
</message>
</context>
<context>
<name>FolderListDialog</name>
<message>
<source>Done</source>
<translation>完成</translation>
</message>
<message>
<source>Choose folder</source>
<translation>选择文件夹</translation>
</message>
<message>
<source>Are you sure you want to delete the folder?</source>
<translation>是否确认删除此文件夹</translation>
</message>
<message>
<source>If you delete the </source>
<translation>如果将 </translation>
</message>
<message>
<source> folder and remove it from the list, the folder will no longer appear in the list, but will not be deleted.</source>
<translation> 文件夹从列表中移除则该文件夹不会再出现在列表中但不会被删除</translation>
</message>
</context>
<context>
<name>SwitchSettingCard</name>
<message>
<source>Off</source>
<translation></translation>
</message>
<message>
<source>On</source>
<translation></translation>
</message>
</context>
<context>
<name>CustomColorSettingCard</name>
<message>
<source>Custom color</source>
<translation>自定义颜色</translation>
</message>
<message>
<source>Default color</source>
<translation>默认颜色</translation>
</message>
<message>
<source>Choose color</source>
<translation>选择颜色</translation>
</message>
</context>
<context>
<name>ColorPickerButton</name>
<message>
<source>Choose </source>
<translation>选择</translation>
</message>
</context>
<context>
<name>FolderListSettingCard</name>
<message>
<source>Add folder</source>
<translation>添加文件夹</translation>
</message>
<message>
<source>Choose folder</source>
<translation>选择文件夹</translation>
</message>
<message>
<source>Are you sure you want to delete the folder?</source>
<translation>是否确认删除此文件夹</translation>
</message>
<message>
<source>If you delete the </source>
<translation>如果将 </translation>
</message>
<message>
<source> folder and remove it from the list, the folder will no longer appear in the list, but will not be deleted.</source>
<translation> 文件夹从列表中移除则该文件夹不会再出现在列表中但不会被删除</translation>
</message>
</context>
<!-- Put the translation of your interface below -->
<context>
<name>SettingInterface</name>
<message>
<source>Settings</source>
<translation>设置</translation>
</message>
<message>
<source>Music on this PC</source>
<translation> PC 上的音乐</translation>
</message>
<message>
<source>Local music library</source>
<translation>本地音乐库</translation>
</message>
<message>
<source>Choose folder</source>
<translation>选择文件夹</translation>
</message>
<message>
<source>Download directory</source>
<translation>下载目录</translation>
</message>
<message>
<source>Personalization</source>
<translation>个性化</translation>
</message>
<message>
<source>Use Acrylic effect</source>
<translation>启用亚克力效果</translation>
</message>
<message>
<source>Acrylic effect has better visual experience, but it may cause the window to become stuck</source>
<translation>亚克力效果的视觉体验更好但可能导致窗口卡顿</translation>
</message>
<message>
<source>Application theme</source>
<translation>应用主题</translation>
</message>
<message>
<source>Theme color</source>
<translation>主题色</translation>
</message>
<message>
<source>Change the theme color of you application</source>
<translation>调整你的应用主题颜色</translation>
</message>
<message>
<source>Change the appearance of your application</source>
<translation>调整你的应用外观</translation>
</message>
<message>
<source>Light</source>
<translation>浅色</translation>
</message>
<message>
<source>Dark</source>
<translation>深色</translation>
</message>
<message>
<source>Use system setting</source>
<translation>跟随系统设置</translation>
</message>
<message>
<source>Interface zoom</source>
<translation>界面缩放</translation>
</message>
<message>
<source>Change the size of widgets and fonts</source>
<translation>调整组件和字体的大小</translation>
</message>
<message>
<source>Language</source>
<translation>语言</translation>
</message>
<message>
<source>Set your preferred language for UI</source>
<translation>选择界面所使用的语言</translation>
</message>
<message>
<source>Online Music</source>
<translation>在线音乐</translation>
</message>
<message>
<source>Number of online music displayed on each page</source>
<translation>每页显示的在线歌曲数量</translation>
</message>
<message>
<source>Online music quality</source>
<translation>在线播放音质</translation>
</message>
<message>
<source>Standard quality</source>
<translation>流畅</translation>
</message>
<message>
<source>High quality</source>
<translation>高品</translation>
</message>
<message>
<source>Super quality</source>
<translation>超品</translation>
</message>
<message>
<source>Lossless quality</source>
<translation>无损</translation>
</message>
<message>
<source>Online MV quality</source>
<translation>在线 MV 画质</translation>
</message>
<message>
<source>Full HD</source>
<translation>超清</translation>
</message>
<message>
<source>HD</source>
<translation>高清</translation>
</message>
<message>
<source>SD</source>
<translation>标清</translation>
</message>
<message>
<source>LD</source>
<translation>流畅</translation>
</message>
<message>
<source>Desktop Lyric</source>
<translation>桌面歌词</translation>
</message>
<message>
<source>Choose font</source>
<translation>选择字体</translation>
</message>
<message>
<source>Font</source>
<translation>字体</translation>
</message>
<message>
<source>Foreground color</source>
<translation>前景色</translation>
</message>
<message>
<source>Background color</source>
<translation>背景色</translation>
</message>
<message>
<source>Stroke color</source>
<translation>描边色</translation>
</message>
<message>
<source>Stroke size</source>
<translation>描边大小</translation>
</message>
<message>
<source>Alignment</source>
<translation>对齐方式</translation>
</message>
<message>
<source>Center aligned</source>
<translation>居中对齐</translation>
</message>
<message>
<source>Left aligned</source>
<translation>左对齐</translation>
</message>
<message>
<source>Right aligned</source>
<translation>右对齐</translation>
</message>
<message>
<source>Main Panel</source>
<translation>主面板</translation>
</message>
<message>
<source>Minimize to tray after closing</source>
<translation>关闭后最小化到托盘</translation>
</message>
<message>
<source>PyQt-Fluent-Widgets will continue to run in the background</source>
<translation>PyQt-Fluent-Widgets 将在后台继续运行</translation>
</message>
<message>
<location filename="../../View/setting_interface/setting_interface.py" line="156"/>
<source>Software update</source>
<translation>软件更新</translation>
</message>
<message>
<source>Check for updates when the application starts</source>
<translation>在应用程序启动时检查更新</translation>
</message>
<message>
<source>The new version will be more stable and have more features</source>
<translation>新版本将更加稳定并拥有更多功能建议启用此选项</translation>
</message>
<message>
<source>About</source>
<translation>关于</translation>
</message>
<message>
<source>Open help page</source>
<translation>打开帮助页面</translation>
</message>
<message>
<source>Discover new features and learn useful tips about PyQt-Fluent-Widgets</source>
<translation>发现新功能并了解有关 PyQt-Fluent-Widgets 的使用技巧</translation>
</message>
<message>
<source>Provide feedback</source>
<translation>提供反馈</translation>
</message>
<message>
<source>Help us improve PyQt-Fluent-Widgets by providing feedback</source>
<translation>通过提供反馈帮助我们改进 PyQt-Fluent-Widgets</translation>
</message>
<message>
<source>Check update</source>
<translation>检查更新</translation>
</message>
<message>
<source>Copyright</source>
<translation>版权所有</translation>
</message>
<message>
<source>Version</source>
<translation>当前版本</translation>
</message>
<message>
<source>Configuration updated successfully</source>
<translation>配置更新成功</translation>
</message>
<message>
<source>Configuration takes effect after restart</source>
<translation>配置在重启软件后生效</translation>
</message>
</context>
</TS>
\ 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="#000000" d="M384 1433 q-11 4 -37 13 q-26 9 -59.5 20.5 q-33.5 11.5 -69.5 23.5 q-36 12 -68 22.5 q-32 10.5 -55.5 17 q-23.5 6.5 -30.5 6.5 q-27 0 -45.5 -19.5 q-18.5 -19.5 -18.5 -45.5 q0 -7 6 -31.5 q6 -24.5 15.5 -58 q9.5 -33.5 20.5 -72 q11 -38.5 21.5 -73.5 q10.5 -35 19 -62 q8.5 -27 11.5 -38 q-94 -173 -94 -368 q0 -106 27.5 -204 q27.5 -98 77.5 -183.5 q50 -85.5 120 -155.5 q70 -70 155.5 -120 q85.5 -50 183.5 -77.5 q98 -27.5 204 -27.5 q159 0 298.5 60.5 q139.5 60.5 244 165 q104.5 104.5 165 244 q60.5 139.5 60.5 298.5 q0 106 -27.5 204 q-27.5 98 -77.5 183.5 q-50 85.5 -120 155.5 q-70 70 -155.5 120 q-85.5 50 -183.5 77.5 q-98 27.5 -204 27.5 q-101 0 -198.5 -26 q-97.5 -26 -185.5 -77 ZM1408 768 q0 -133 -50 -249.5 q-50 -116.5 -137 -203.5 q-87 -87 -203.5 -137 q-116.5 -50 -249.5 -50 q-133 0 -249.5 50 q-116.5 50 -203.5 137 q-87 87 -137 203.5 q-50 116.5 -50 249.5 q0 91 23.5 169 q23.5 78 65.5 158 q5 8 7 15.5 q2 7.5 2 17.5 q0 8 -4 26.5 q-4 18.5 -10.5 42 q-6.5 23.5 -14.5 50 q-8 26.5 -15.5 51 q-7.5 24.5 -13.5 45 q-6 20.5 -9 30.5 q14 -4 48 -16.5 q34 -12.5 71.5 -25 q37.5 -12.5 69.5 -22.5 q32 -10 42 -10 q19 0 36 10 q42 24 82 42 q40 18 81.5 31 q41.5 13 85.5 19.5 q44 6.5 93 6.5 q133 0 249.5 -50 q116.5 -50 203.5 -137 q87 -87 137 -203.5 q50 -116.5 50 -249.5 ZM576 704 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 l384 0 q26 0 45 19 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 l-384 0 ZM607 1649 q79 15 161 15 q93 122 225.5 189 q132.5 67 286.5 67 q49 0 92.5 -6.5 q43.5 -6.5 85 -19 q41.5 -12.5 82 -31 q40.5 -18.5 82.5 -42.5 q17 -10 36 -10 q10 0 42 10 q32 10 69.5 22.5 q37.5 12.5 71.5 25 q34 12.5 48 16.5 q-3 -10 -9 -30.5 q-6 -20.5 -13.5 -45 q-7.5 -24.5 -15.5 -51 q-8 -26.5 -14.5 -50 q-6.5 -23.5 -10.5 -42 q-4 -18.5 -4 -26.5 q0 -10 2 -17.5 q2 -7.5 7 -15.5 q21 -40 37.5 -79 q16.5 -39 28 -79 q11.5 -40 17.5 -81.5 q6 -41.5 6 -87.5 q0 -75 -17.5 -147.5 q-17.5 -72.5 -50.5 -138.5 q-33 -66 -80.5 -123.5 q-47.5 -57.5 -107.5 -102.5 q0 -79 -14 -161 q91 49 164.5 121 q73.5 72 125.5 159 q52 87 80 186 q28 99 28 202 q0 100 -22.5 192.5 q-22.5 92.5 -70.5 180.5 q3 11 11.5 38.5 q8.5 27.5 18.5 62.5 q10 35 21.5 73.5 q11.5 38.5 20.5 72 q9 33.5 15 57.5 q6 24 6 31 q0 26 -18.5 45.5 q-18.5 19.5 -45.5 19.5 q-7 0 -30.5 -6.5 q-23.5 -6.5 -55 -17 q-31.5 -10.5 -68 -22.5 q-36.5 -12 -69.5 -23.5 q-33 -11.5 -59 -20.5 q-26 -9 -37 -13 q-94 53 -190 78 q-96 25 -203 25 q-103 0 -201.5 -28.5 q-98.5 -28.5 -185 -80.5 q-86.5 -52 -158 -126 q-71.5 -74 -120.5 -164 ZM576 960 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 l256 0 q26 0 45 19 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 l-256 0 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="M384 1433 q-11 4 -37 13 q-26 9 -59.5 20.5 q-33.5 11.5 -69.5 23.5 q-36 12 -68 22.5 q-32 10.5 -55.5 17 q-23.5 6.5 -30.5 6.5 q-27 0 -45.5 -19.5 q-18.5 -19.5 -18.5 -45.5 q0 -7 6 -31.5 q6 -24.5 15.5 -58 q9.5 -33.5 20.5 -72 q11 -38.5 21.5 -73.5 q10.5 -35 19 -62 q8.5 -27 11.5 -38 q-94 -173 -94 -368 q0 -106 27.5 -204 q27.5 -98 77.5 -183.5 q50 -85.5 120 -155.5 q70 -70 155.5 -120 q85.5 -50 183.5 -77.5 q98 -27.5 204 -27.5 q159 0 298.5 60.5 q139.5 60.5 244 165 q104.5 104.5 165 244 q60.5 139.5 60.5 298.5 q0 106 -27.5 204 q-27.5 98 -77.5 183.5 q-50 85.5 -120 155.5 q-70 70 -155.5 120 q-85.5 50 -183.5 77.5 q-98 27.5 -204 27.5 q-101 0 -198.5 -26 q-97.5 -26 -185.5 -77 ZM1408 768 q0 -133 -50 -249.5 q-50 -116.5 -137 -203.5 q-87 -87 -203.5 -137 q-116.5 -50 -249.5 -50 q-133 0 -249.5 50 q-116.5 50 -203.5 137 q-87 87 -137 203.5 q-50 116.5 -50 249.5 q0 91 23.5 169 q23.5 78 65.5 158 q5 8 7 15.5 q2 7.5 2 17.5 q0 8 -4 26.5 q-4 18.5 -10.5 42 q-6.5 23.5 -14.5 50 q-8 26.5 -15.5 51 q-7.5 24.5 -13.5 45 q-6 20.5 -9 30.5 q14 -4 48 -16.5 q34 -12.5 71.5 -25 q37.5 -12.5 69.5 -22.5 q32 -10 42 -10 q19 0 36 10 q42 24 82 42 q40 18 81.5 31 q41.5 13 85.5 19.5 q44 6.5 93 6.5 q133 0 249.5 -50 q116.5 -50 203.5 -137 q87 -87 137 -203.5 q50 -116.5 50 -249.5 ZM576 704 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 l384 0 q26 0 45 19 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 l-384 0 ZM607 1649 q79 15 161 15 q93 122 225.5 189 q132.5 67 286.5 67 q49 0 92.5 -6.5 q43.5 -6.5 85 -19 q41.5 -12.5 82 -31 q40.5 -18.5 82.5 -42.5 q17 -10 36 -10 q10 0 42 10 q32 10 69.5 22.5 q37.5 12.5 71.5 25 q34 12.5 48 16.5 q-3 -10 -9 -30.5 q-6 -20.5 -13.5 -45 q-7.5 -24.5 -15.5 -51 q-8 -26.5 -14.5 -50 q-6.5 -23.5 -10.5 -42 q-4 -18.5 -4 -26.5 q0 -10 2 -17.5 q2 -7.5 7 -15.5 q21 -40 37.5 -79 q16.5 -39 28 -79 q11.5 -40 17.5 -81.5 q6 -41.5 6 -87.5 q0 -75 -17.5 -147.5 q-17.5 -72.5 -50.5 -138.5 q-33 -66 -80.5 -123.5 q-47.5 -57.5 -107.5 -102.5 q0 -79 -14 -161 q91 49 164.5 121 q73.5 72 125.5 159 q52 87 80 186 q28 99 28 202 q0 100 -22.5 192.5 q-22.5 92.5 -70.5 180.5 q3 11 11.5 38.5 q8.5 27.5 18.5 62.5 q10 35 21.5 73.5 q11.5 38.5 20.5 72 q9 33.5 15 57.5 q6 24 6 31 q0 26 -18.5 45.5 q-18.5 19.5 -45.5 19.5 q-7 0 -30.5 -6.5 q-23.5 -6.5 -55 -17 q-31.5 -10.5 -68 -22.5 q-36.5 -12 -69.5 -23.5 q-33 -11.5 -59 -20.5 q-26 -9 -37 -13 q-94 53 -190 78 q-96 25 -203 25 q-103 0 -201.5 -28.5 q-98.5 -28.5 -185 -80.5 q-86.5 -52 -158 -126 q-71.5 -74 -120.5 -164 ZM576 960 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 l256 0 q26 0 45 19 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 l-256 0 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="#000000" d="M251 2048 q-50 0 -95.5 -20.5 q-45.5 -20.5 -80 -55 q-34.5 -34.5 -55 -80 q-20.5 -45.5 -20.5 -95.5 l0 -1546 q0 -50 20.5 -95.5 q20.5 -45.5 55 -80 q34.5 -34.5 80 -55 q45.5 -20.5 95.5 -20.5 l1546 0 q50 0 95.5 20.5 q45.5 20.5 80 55 q34.5 34.5 55 80 q20.5 45.5 20.5 95.5 l0 1546 q0 50 -20.5 95.5 q-20.5 45.5 -55 80 q-34.5 34.5 -80 55 q-45.5 20.5 -95.5 20.5 l-1546 0 ZM1792 1920 q27 0 50 -10 q23 -10 40.5 -27.5 q17.5 -17.5 27.5 -40.5 q10 -23 10 -50 l0 -1536 q0 -26 -10 -49.5 q-10 -23.5 -27.5 -41 q-17.5 -17.5 -41 -27.5 q-23.5 -10 -49.5 -10 l-1536 0 q-27 0 -50 10 q-23 10 -40.5 27.5 q-17.5 17.5 -27.5 40.5 q-10 23 -10 50 l0 1536 q0 27 10 50.5 q10 23.5 27 40.5 q17 17 40.5 27 q23.5 10 50.5 10 l1536 0 ZM384 960 q0 -26 19 -45 q19 -19 45 -19 q26 0 45 19 l339 338 l723 -722 q19 -19 45 -19 q26 0 45 19 q19 19 19 45 q0 26 -19 45 l-768 768 q-19 19 -45 19 q-26 0 -45 -19 l-384 -384 q-19 -19 -19 -45 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="M251 2048 q-50 0 -95.5 -20.5 q-45.5 -20.5 -80 -55 q-34.5 -34.5 -55 -80 q-20.5 -45.5 -20.5 -95.5 l0 -1546 q0 -50 20.5 -95.5 q20.5 -45.5 55 -80 q34.5 -34.5 80 -55 q45.5 -20.5 95.5 -20.5 l1546 0 q50 0 95.5 20.5 q45.5 20.5 80 55 q34.5 34.5 55 80 q20.5 45.5 20.5 95.5 l0 1546 q0 50 -20.5 95.5 q-20.5 45.5 -55 80 q-34.5 34.5 -80 55 q-45.5 20.5 -95.5 20.5 l-1546 0 ZM1792 1920 q27 0 50 -10 q23 -10 40.5 -27.5 q17.5 -17.5 27.5 -40.5 q10 -23 10 -50 l0 -1536 q0 -26 -10 -49.5 q-10 -23.5 -27.5 -41 q-17.5 -17.5 -41 -27.5 q-23.5 -10 -49.5 -10 l-1536 0 q-27 0 -50 10 q-23 10 -40.5 27.5 q-17.5 17.5 -27.5 40.5 q-10 23 -10 50 l0 1536 q0 27 10 50.5 q10 23.5 27 40.5 q17 17 40.5 27 q23.5 10 50.5 10 l1536 0 ZM384 960 q0 -26 19 -45 q19 -19 45 -19 q26 0 45 19 l339 338 l723 -722 q19 -19 45 -19 q26 0 45 19 q19 19 19 45 q0 26 -19 45 l-768 768 q-19 19 -45 19 q-26 0 -45 -19 l-384 -384 q-19 -19 -19 -45 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="#000000" d="M960 192 l0 -128 q0 -26 19 -45 q19 -19 45 -19 q26 0 45 19 q19 19 19 45 l0 128 q0 26 -19 45 q-19 19 -45 19 q-26 0 -45 -19 q-19 -19 -19 -45 ZM512 448 q0 26 -19 45 q-19 19 -45 19 q-26 0 -45 -19 l-128 -128 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 q26 0 45 19 l128 128 q19 19 19 45 ZM1728 256 q26 0 45 19 q19 19 19 45 q0 26 -19 45 l-128 128 q-19 19 -45 19 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 l128 -128 q19 -19 45 -19 ZM1536 1024 l0 10 q0 104 -41.5 195.5 q-41.5 91.5 -112 159.5 q-70.5 68 -163 107.5 q-92.5 39.5 -195.5 39.5 q-106 0 -199.5 -40 q-93.5 -40 -163 -109.5 q-69.5 -69.5 -109.5 -163 q-40 -93.5 -40 -199.5 q0 -106 40 -199.5 q40 -93.5 109.5 -163 q69.5 -69.5 163 -109.5 q93.5 -40 199.5 -40 q106 0 199.5 40 q93.5 40 163 109.5 q69.5 69.5 109.5 163 q40 93.5 40 199.5 ZM1024 1408 l8 0 q78 0 146.5 -31 q68.5 -31 119.5 -84 q51 -53 80.5 -122.5 q29.5 -69.5 29.5 -146.5 q0 -77 -29.5 -146.5 q-29.5 -69.5 -80.5 -122.5 q-51 -53 -119.5 -84 q-68.5 -31 -146.5 -31 l-8 0 l0 768 ZM192 960 q26 0 45 19 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 l-128 0 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 l128 0 ZM1984 960 q26 0 45 19 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 l-128 0 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 l128 0 ZM448 1536 q26 0 45 19 q19 19 19 45 q0 26 -19 45 l-128 128 q-19 19 -45 19 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 l128 -128 q19 -19 45 -19 ZM1792 1728 q0 26 -19 45 q-19 19 -45 19 q-26 0 -45 -19 l-128 -128 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 q26 0 45 19 l128 128 q19 19 19 45 ZM1088 1856 l0 128 q0 26 -19 45 q-19 19 -45 19 q-26 0 -45 -19 q-19 -19 -19 -45 l0 -128 q0 -26 19 -45 q19 -19 45 -19 q26 0 45 19 q19 19 19 45 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="M960 192 l0 -128 q0 -26 19 -45 q19 -19 45 -19 q26 0 45 19 q19 19 19 45 l0 128 q0 26 -19 45 q-19 19 -45 19 q-26 0 -45 -19 q-19 -19 -19 -45 ZM512 448 q0 26 -19 45 q-19 19 -45 19 q-26 0 -45 -19 l-128 -128 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 q26 0 45 19 l128 128 q19 19 19 45 ZM1728 256 q26 0 45 19 q19 19 19 45 q0 26 -19 45 l-128 128 q-19 19 -45 19 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 l128 -128 q19 -19 45 -19 ZM1536 1024 l0 10 q0 104 -41.5 195.5 q-41.5 91.5 -112 159.5 q-70.5 68 -163 107.5 q-92.5 39.5 -195.5 39.5 q-106 0 -199.5 -40 q-93.5 -40 -163 -109.5 q-69.5 -69.5 -109.5 -163 q-40 -93.5 -40 -199.5 q0 -106 40 -199.5 q40 -93.5 109.5 -163 q69.5 -69.5 163 -109.5 q93.5 -40 199.5 -40 q106 0 199.5 40 q93.5 40 163 109.5 q69.5 69.5 109.5 163 q40 93.5 40 199.5 ZM1024 1408 l8 0 q78 0 146.5 -31 q68.5 -31 119.5 -84 q51 -53 80.5 -122.5 q29.5 -69.5 29.5 -146.5 q0 -77 -29.5 -146.5 q-29.5 -69.5 -80.5 -122.5 q-51 -53 -119.5 -84 q-68.5 -31 -146.5 -31 l-8 0 l0 768 ZM192 960 q26 0 45 19 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 l-128 0 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 l128 0 ZM1984 960 q26 0 45 19 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 l-128 0 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 l128 0 ZM448 1536 q26 0 45 19 q19 19 19 45 q0 26 -19 45 l-128 128 q-19 19 -45 19 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 l128 -128 q19 -19 45 -19 ZM1792 1728 q0 26 -19 45 q-19 19 -45 19 q-26 0 -45 -19 l-128 -128 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 q26 0 45 19 l128 128 q19 19 19 45 ZM1088 1856 l0 128 q0 26 -19 45 q-19 19 -45 19 q-26 0 -45 -19 q-19 -19 -19 -45 l0 -128 q0 -26 19 -45 q19 -19 45 -19 q26 0 45 19 q19 19 19 45 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="#000000" d="M1792 784 l0 1008 q0 53 -20 99.5 q-20 46.5 -55 81.5 q-35 35 -81.5 55 q-46.5 20 -99.5 20 l-1024 0 q-53 0 -99.5 -20 q-46.5 -20 -81.5 -55 q-35 -35 -55 -81.5 q-20 -46.5 -20 -99.5 l0 -1536 q0 -53 20 -99.5 q20 -46.5 55 -81.5 q35 -35 81.5 -55 q46.5 -20 99.5 -20 l496 0 q51 0 98 19.5 q47 19.5 83 55.5 l528 528 q36 36 55.5 83 q19.5 47 19.5 98 ZM1664 784 q0 -4 0 -8 q0 -4 -1 -8 l-383 0 q-53 0 -99.5 -20 q-46.5 -20 -81.5 -55 q-35 -35 -55 -81.5 q-20 -46.5 -20 -99.5 l0 -383 q-4 -1 -8 -1 q-4 0 -8 0 l-496 0 q-27 0 -50 10 q-23 10 -40.5 27.5 q-17.5 17.5 -27.5 40.5 q-10 23 -10 50 l0 1536 q0 27 10 50.5 q10 23.5 27 40.5 q17 17 40.5 27 q23.5 10 50.5 10 l1024 0 q27 0 50 -10 q23 -10 40.5 -27.5 q17.5 -17.5 27.5 -40.5 q10 -23 10 -50 l0 -1008 ZM1574 640 l-422 -422 l0 294 q0 27 10 50.5 q10 23.5 27 40.5 q17 17 40.5 27 q23.5 10 50.5 10 l294 0 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="M1792 784 l0 1008 q0 53 -20 99.5 q-20 46.5 -55 81.5 q-35 35 -81.5 55 q-46.5 20 -99.5 20 l-1024 0 q-53 0 -99.5 -20 q-46.5 -20 -81.5 -55 q-35 -35 -55 -81.5 q-20 -46.5 -20 -99.5 l0 -1536 q0 -53 20 -99.5 q20 -46.5 55 -81.5 q35 -35 81.5 -55 q46.5 -20 99.5 -20 l496 0 q51 0 98 19.5 q47 19.5 83 55.5 l528 528 q36 36 55.5 83 q19.5 47 19.5 98 ZM1664 784 q0 -4 0 -8 q0 -4 -1 -8 l-383 0 q-53 0 -99.5 -20 q-46.5 -20 -81.5 -55 q-35 -35 -55 -81.5 q-20 -46.5 -20 -99.5 l0 -383 q-4 -1 -8 -1 q-4 0 -8 0 l-496 0 q-27 0 -50 10 q-23 10 -40.5 27.5 q-17.5 17.5 -27.5 40.5 q-10 23 -10 50 l0 1536 q0 27 10 50.5 q10 23.5 27 40.5 q17 17 40.5 27 q23.5 10 50.5 10 l1024 0 q27 0 50 -10 q23 -10 40.5 -27.5 q17.5 -17.5 27.5 -40.5 q10 -23 10 -50 l0 -1008 ZM1574 640 l-422 -422 l0 294 q0 27 10 50.5 q10 23.5 27 40.5 q17 17 40.5 27 q23.5 10 50.5 10 l294 0 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="#000000" d="M340.62 2048 q-56.59 0 -106.24 -21.36 q-49.65 -21.36 -87.03 -58.73 q-37.37 -37.38 -58.73 -87.03 q-21.36 -49.65 -21.36 -106.24 l0 -831.8 q0 -40.58 16.02 -79.02 q16.02 -38.44 43.78 -66.2 l728.22 -727.16 q34.17 -34.17 77.42 -52.32 q43.25 -18.15 91.29 -18.15 q48.05 0 91.3 18.15 q43.24 18.15 77.41 52.32 l728.22 727.16 q27.77 27.76 43.79 66.2 q16.01 38.44 16.01 79.02 l0 831.8 q0 56.59 -21.36 106.24 q-21.36 49.65 -58.73 87.03 q-37.38 37.38 -87.03 58.73 q-49.65 21.36 -106.24 21.36 l-410.03 0 q-28.83 0 -53.92 -10.68 q-25.09 -10.68 -43.24 -28.83 q-18.15 -18.15 -28.83 -43.25 q-10.67 -25.09 -10.67 -53.92 l0 -546.7 l-273.36 0 l0 546.7 q0 28.83 -10.68 53.39 q-10.67 24.56 -29.36 43.24 q-18.69 18.69 -43.25 29.37 q-24.56 10.68 -53.39 10.68 l-410.03 0 ZM750.65 1911.32 l0 -546.7 q0 -28.83 10.68 -53.39 q10.67 -24.56 29.37 -43.24 q18.69 -18.69 43.24 -29.36 q24.56 -10.67 53.39 -10.67 l273.36 0 q27.76 0 52.85 10.67 q25.09 10.67 43.78 29.36 q18.69 18.68 29.37 43.78 q10.67 25.1 10.67 52.86 l0 546.7 l410.03 0 q28.83 0 53.39 -10.67 q24.56 -10.67 43.24 -29.36 q18.69 -18.68 29.36 -43.24 q10.67 -24.56 10.67 -53.39 l0 -831.8 q0 -27.76 -20.28 -48.05 l-727.16 -728.23 q-29.9 -29.89 -72.61 -29.89 q-42.71 0 -72.61 29.89 l-727.16 728.23 q-20.28 20.29 -20.28 48.05 l0 831.8 q0 28.83 10.68 53.92 q10.68 25.09 28.83 43.24 q18.16 18.15 43.25 28.83 q25.09 10.67 53.92 10.67 l410.03 0 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="M340.62 2048 q-56.59 0 -106.24 -21.36 q-49.65 -21.36 -87.03 -58.73 q-37.37 -37.38 -58.73 -87.03 q-21.36 -49.65 -21.36 -106.24 l0 -831.8 q0 -40.58 16.02 -79.02 q16.02 -38.44 43.78 -66.2 l728.22 -727.16 q34.17 -34.17 77.42 -52.32 q43.25 -18.15 91.29 -18.15 q48.05 0 91.3 18.15 q43.24 18.15 77.41 52.32 l728.22 727.16 q27.77 27.76 43.79 66.2 q16.01 38.44 16.01 79.02 l0 831.8 q0 56.59 -21.36 106.24 q-21.36 49.65 -58.73 87.03 q-37.38 37.38 -87.03 58.73 q-49.65 21.36 -106.24 21.36 l-410.03 0 q-28.83 0 -53.92 -10.68 q-25.09 -10.68 -43.24 -28.83 q-18.15 -18.15 -28.83 -43.25 q-10.67 -25.09 -10.67 -53.92 l0 -546.7 l-273.36 0 l0 546.7 q0 28.83 -10.68 53.39 q-10.67 24.56 -29.36 43.24 q-18.69 18.69 -43.25 29.37 q-24.56 10.68 -53.39 10.68 l-410.03 0 ZM750.65 1911.32 l0 -546.7 q0 -28.83 10.68 -53.39 q10.67 -24.56 29.37 -43.24 q18.69 -18.69 43.24 -29.36 q24.56 -10.67 53.39 -10.67 l273.36 0 q27.76 0 52.85 10.67 q25.09 10.67 43.78 29.36 q18.69 18.68 29.37 43.78 q10.67 25.1 10.67 52.86 l0 546.7 l410.03 0 q28.83 0 53.39 -10.67 q24.56 -10.67 43.24 -29.36 q18.69 -18.68 29.36 -43.24 q10.67 -24.56 10.67 -53.39 l0 -831.8 q0 -27.76 -20.28 -48.05 l-727.16 -728.23 q-29.9 -29.89 -72.61 -29.89 q-42.71 0 -72.61 29.89 l-727.16 728.23 q-20.28 20.29 -20.28 48.05 l0 831.8 q0 28.83 10.68 53.92 q10.68 25.09 28.83 43.24 q18.16 18.15 43.25 28.83 q25.09 10.67 53.92 10.67 l410.03 0 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="#000000" d="M1690.29 0 q72 0 137.14 29.14 q65.14 29.14 113.71 77.72 q48.57 48.57 77.72 113.71 q29.14 65.14 29.14 137.14 l0 1332.58 q0 72 -29.14 137.14 q-29.14 65.14 -77.72 113.71 q-48.57 48.57 -113.71 77.72 q-65.14 29.14 -137.14 29.14 l-1332.58 0 q-72 0 -137.14 -29.14 q-65.14 -29.14 -113.71 -77.72 q-48.57 -48.57 -77.72 -113.71 q-29.14 -65.14 -29.14 -137.14 l0 -1332.58 q0 -72 29.14 -137.14 q29.14 -65.14 77.72 -113.71 q48.57 -48.57 113.71 -77.72 q65.14 -29.14 137.14 -29.14 l1332.58 0 ZM365.71 146.29 q-44.57 0 -84.57 17.14 q-40 17.14 -70.28 47.42 q-30.28 30.28 -47.42 70.28 q-17.14 40 -17.14 84.57 l0 950.86 l1024 0 l0 -1170.28 l-804.58 0 ZM1901.71 365.71 q0 -44.57 -17.14 -84.57 q-17.14 -40 -47.43 -70.28 q-30.29 -30.28 -70.29 -47.42 q-40 -17.14 -84.57 -17.14 l-365.72 0 l0 438.85 l585.14 0 l0 -219.43 ZM1901.71 731.43 l-585.14 0 l0 585.14 l585.14 0 l0 -585.14 ZM146.29 1682.29 q0 44.57 17.14 84.57 q17.14 40 47.42 70.29 q30.28 30.29 70.28 47.43 q40 17.14 84.57 17.14 l365.72 0 l0 -438.85 l-585.14 0 l0 219.43 ZM1682.29 1901.71 q44.57 0 84.57 -17.14 q40 -17.14 70.29 -47.43 q30.29 -30.29 47.43 -70.29 q17.14 -40 17.14 -84.57 l0 -219.43 l-1024 0 l0 438.85 l804.58 0 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="M1690.29 0 q72 0 137.14 29.14 q65.14 29.14 113.71 77.72 q48.57 48.57 77.72 113.71 q29.14 65.14 29.14 137.14 l0 1332.58 q0 72 -29.14 137.14 q-29.14 65.14 -77.72 113.71 q-48.57 48.57 -113.71 77.72 q-65.14 29.14 -137.14 29.14 l-1332.58 0 q-72 0 -137.14 -29.14 q-65.14 -29.14 -113.71 -77.72 q-48.57 -48.57 -77.72 -113.71 q-29.14 -65.14 -29.14 -137.14 l0 -1332.58 q0 -72 29.14 -137.14 q29.14 -65.14 77.72 -113.71 q48.57 -48.57 113.71 -77.72 q65.14 -29.14 137.14 -29.14 l1332.58 0 ZM365.71 146.29 q-44.57 0 -84.57 17.14 q-40 17.14 -70.28 47.42 q-30.28 30.28 -47.42 70.28 q-17.14 40 -17.14 84.57 l0 950.86 l1024 0 l0 -1170.28 l-804.58 0 ZM1901.71 365.71 q0 -44.57 -17.14 -84.57 q-17.14 -40 -47.43 -70.28 q-30.29 -30.28 -70.29 -47.42 q-40 -17.14 -84.57 -17.14 l-365.72 0 l0 438.85 l585.14 0 l0 -219.43 ZM1901.71 731.43 l-585.14 0 l0 585.14 l585.14 0 l0 -585.14 ZM146.29 1682.29 q0 44.57 17.14 84.57 q17.14 40 47.42 70.29 q30.28 30.29 70.28 47.43 q40 17.14 84.57 17.14 l365.72 0 l0 -438.85 l-585.14 0 l0 219.43 ZM1682.29 1901.71 q44.57 0 84.57 -17.14 q40 -17.14 70.29 -47.43 q30.29 -30.29 47.43 -70.29 q17.14 -40 17.14 -84.57 l0 -219.43 l-1024 0 l0 438.85 l804.58 0 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="#000000" d="M448 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 -1536 q0 -39 15 -74 q15 -35 41.5 -61.5 q26.5 -26.5 61.5 -41.5 q35 -15 74 -15 l203 0 q10 -29 28 -52.5 q18 -23.5 42 -40.5 q24 -17 52 -26 q28 -9 59 -9 l384 0 q31 0 59 9 q28 9 52 26 q24 17 42 40.5 q18 23.5 28 52.5 l203 0 q39 0 74 15 q35 15 61.5 41.5 q26.5 26.5 41.5 61.5 q15 35 15 74 l0 1536 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-1152 0 ZM1216 256 q26 0 45 -19 q19 -19 19 -45 q0 -26 -19 -45 q-19 -19 -45 -19 l-384 0 q-26 0 -45 19 q-19 19 -19 45 q0 26 19 45 q19 19 45 19 l384 0 ZM1600 1920 q26 0 45 -19 q19 -19 19 -45 l0 -1536 q0 -26 -19 -45 q-19 -19 -45 -19 l-203 0 q-10 29 -28 52.5 q-18 23.5 -42 40 q-24 16.5 -52.5 26 q-28.5 9.5 -58.5 9.5 l-384 0 q-30 0 -58 -9.5 q-28 -9.5 -52 -26 q-24 -16.5 -42.5 -40 q-18.5 -23.5 -28.5 -52.5 l-203 0 q-26 0 -45 19 q-19 19 -19 45 l0 1536 q0 26 19 45 q19 19 45 19 l1152 0 ZM512 832 q0 -27 10 -50 q10 -23 27.5 -40.5 q17.5 -17.5 40.5 -27.5 q23 -10 50 -10 q26 0 49.5 10 q23.5 10 41 27.5 q17.5 17.5 27.5 41 q10 23.5 10 49.5 q0 27 -10 50 q-10 23 -27.5 40.5 q-17.5 17.5 -40.5 27.5 q-23 10 -50 10 q-27 0 -50.5 -10 q-23.5 -10 -40.5 -27 q-17 -17 -27 -40.5 q-10 -23.5 -10 -50.5 ZM960 896 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 l512 0 q26 0 45 19 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 l-512 0 ZM512 1216 q0 -27 10 -50 q10 -23 27.5 -40.5 q17.5 -17.5 40.5 -27.5 q23 -10 50 -10 q26 0 49.5 10 q23.5 10 41 27.5 q17.5 17.5 27.5 41 q10 23.5 10 49.5 q0 27 -10 50 q-10 23 -27.5 40.5 q-17.5 17.5 -40.5 27.5 q-23 10 -50 10 q-27 0 -50.5 -10 q-23.5 -10 -40.5 -27 q-17 -17 -27 -40.5 q-10 -23.5 -10 -50.5 ZM960 1280 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 l512 0 q26 0 45 19 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 l-512 0 ZM512 1600 q0 -27 10 -50 q10 -23 27.5 -40.5 q17.5 -17.5 40.5 -27.5 q23 -10 50 -10 q26 0 49.5 10 q23.5 10 41 27.5 q17.5 17.5 27.5 41 q10 23.5 10 49.5 q0 27 -10 50 q-10 23 -27.5 40.5 q-17.5 17.5 -40.5 27.5 q-23 10 -50 10 q-27 0 -50.5 -10 q-23.5 -10 -40.5 -27 q-17 -17 -27 -40.5 q-10 -23.5 -10 -50.5 ZM960 1664 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 l512 0 q26 0 45 19 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 l-512 0 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="M448 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 -1536 q0 -39 15 -74 q15 -35 41.5 -61.5 q26.5 -26.5 61.5 -41.5 q35 -15 74 -15 l203 0 q10 -29 28 -52.5 q18 -23.5 42 -40.5 q24 -17 52 -26 q28 -9 59 -9 l384 0 q31 0 59 9 q28 9 52 26 q24 17 42 40.5 q18 23.5 28 52.5 l203 0 q39 0 74 15 q35 15 61.5 41.5 q26.5 26.5 41.5 61.5 q15 35 15 74 l0 1536 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-1152 0 ZM1216 256 q26 0 45 -19 q19 -19 19 -45 q0 -26 -19 -45 q-19 -19 -45 -19 l-384 0 q-26 0 -45 19 q-19 19 -19 45 q0 26 19 45 q19 19 45 19 l384 0 ZM1600 1920 q26 0 45 -19 q19 -19 19 -45 l0 -1536 q0 -26 -19 -45 q-19 -19 -45 -19 l-203 0 q-10 29 -28 52.5 q-18 23.5 -42 40 q-24 16.5 -52.5 26 q-28.5 9.5 -58.5 9.5 l-384 0 q-30 0 -58 -9.5 q-28 -9.5 -52 -26 q-24 -16.5 -42.5 -40 q-18.5 -23.5 -28.5 -52.5 l-203 0 q-26 0 -45 19 q-19 19 -19 45 l0 1536 q0 26 19 45 q19 19 45 19 l1152 0 ZM512 832 q0 -27 10 -50 q10 -23 27.5 -40.5 q17.5 -17.5 40.5 -27.5 q23 -10 50 -10 q26 0 49.5 10 q23.5 10 41 27.5 q17.5 17.5 27.5 41 q10 23.5 10 49.5 q0 27 -10 50 q-10 23 -27.5 40.5 q-17.5 17.5 -40.5 27.5 q-23 10 -50 10 q-27 0 -50.5 -10 q-23.5 -10 -40.5 -27 q-17 -17 -27 -40.5 q-10 -23.5 -10 -50.5 ZM960 896 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 l512 0 q26 0 45 19 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 l-512 0 ZM512 1216 q0 -27 10 -50 q10 -23 27.5 -40.5 q17.5 -17.5 40.5 -27.5 q23 -10 50 -10 q26 0 49.5 10 q23.5 10 41 27.5 q17.5 17.5 27.5 41 q10 23.5 10 49.5 q0 27 -10 50 q-10 23 -27.5 40.5 q-17.5 17.5 -40.5 27.5 q-23 10 -50 10 q-27 0 -50.5 -10 q-23.5 -10 -40.5 -27 q-17 -17 -27 -40.5 q-10 -23.5 -10 -50.5 ZM960 1280 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 l512 0 q26 0 45 19 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 l-512 0 ZM512 1600 q0 -27 10 -50 q10 -23 27.5 -40.5 q17.5 -17.5 40.5 -27.5 q23 -10 50 -10 q26 0 49.5 10 q23.5 10 41 27.5 q17.5 17.5 27.5 41 q10 23.5 10 49.5 q0 27 -10 50 q-10 23 -27.5 40.5 q-17.5 17.5 -40.5 27.5 q-23 10 -50 10 q-27 0 -50.5 -10 q-23.5 -10 -40.5 -27 q-17 -17 -27 -40.5 q-10 -23.5 -10 -50.5 ZM960 1664 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 l512 0 q26 0 45 19 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 l-512 0 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="#000000" d="M0 1984 q0 -26 8.5 -54 q8.5 -28 14.5 -53 q23 -95 48 -188 q25 -93 48 -188 q-59 -110 -89 -230 q-30 -120 -30 -245 q0 -141 36.5 -272.5 q36.5 -131.5 103 -245.5 q66.5 -114 160 -207.5 q93.5 -93.5 207.5 -160.5 q114 -67 245 -103.5 q131 -36.5 272 -36.5 q141 0 271.5 36.5 q130.5 36.5 244.5 103.5 q114 67 207.5 160 q93.5 93 160.5 207 q67 114 103.5 244.5 q36.5 130.5 36.5 271.5 q0 140 -36.5 270.5 q-36.5 130.5 -102.5 244.5 q-66 114 -159 208 q-93 94 -206.5 161 q-113.5 67 -243.5 104 q-130 37 -271 37 q-124 0 -244 -28.5 q-120 -28.5 -230 -85.5 l-476 112 q-10 2 -15 2 q-27 0 -45.5 -18.5 q-18.5 -18.5 -18.5 -45.5 ZM1020 1920 q124 0 239 -32 q115 -32 215 -90 q100 -58 182.5 -139.5 q82.5 -81.5 141 -181.5 q58.5 -100 90.5 -215 q32 -115 32 -239 q0 -124 -32 -238.5 q-32 -114.5 -90.5 -213.5 q-58.5 -99 -140.5 -181 q-82 -82 -182 -140 q-100 -58 -214.5 -90 q-114.5 -32 -237.5 -32 q-123 0 -237.5 32 q-114.5 32 -214 90 q-99.5 58 -181 139.5 q-81.5 81.5 -140 180.5 q-58.5 99 -90.5 213.5 q-32 114.5 -32 237.5 q0 65 8 120 q8 55 23 107.5 q15 52.5 36 104.5 q21 52 48 109 q8 16 8 31 q0 11 -6 41 q-6 30 -16 69 q-10 39 -21.5 84 q-11.5 45 -22.5 86 q-11 41 -20 74.5 q-9 33.5 -13 49.5 q68 -16 134.5 -32 q66.5 -16 134.5 -33 q34 -8 71 -19 q37 -11 72 -11 q8 0 15 2.5 q7 2.5 15 5.5 q54 25 104.5 45.5 q50.5 20.5 101.5 34.5 q51 14 105 22 q54 8 115 8 ZM704 896 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 l640 0 q26 0 45 19 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 l-640 0 ZM704 1280 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 l384 0 q26 0 45 19 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 l-384 0 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="M0 1984 q0 -26 8.5 -54 q8.5 -28 14.5 -53 q23 -95 48 -188 q25 -93 48 -188 q-59 -110 -89 -230 q-30 -120 -30 -245 q0 -141 36.5 -272.5 q36.5 -131.5 103 -245.5 q66.5 -114 160 -207.5 q93.5 -93.5 207.5 -160.5 q114 -67 245 -103.5 q131 -36.5 272 -36.5 q141 0 271.5 36.5 q130.5 36.5 244.5 103.5 q114 67 207.5 160 q93.5 93 160.5 207 q67 114 103.5 244.5 q36.5 130.5 36.5 271.5 q0 140 -36.5 270.5 q-36.5 130.5 -102.5 244.5 q-66 114 -159 208 q-93 94 -206.5 161 q-113.5 67 -243.5 104 q-130 37 -271 37 q-124 0 -244 -28.5 q-120 -28.5 -230 -85.5 l-476 112 q-10 2 -15 2 q-27 0 -45.5 -18.5 q-18.5 -18.5 -18.5 -45.5 ZM1020 1920 q124 0 239 -32 q115 -32 215 -90 q100 -58 182.5 -139.5 q82.5 -81.5 141 -181.5 q58.5 -100 90.5 -215 q32 -115 32 -239 q0 -124 -32 -238.5 q-32 -114.5 -90.5 -213.5 q-58.5 -99 -140.5 -181 q-82 -82 -182 -140 q-100 -58 -214.5 -90 q-114.5 -32 -237.5 -32 q-123 0 -237.5 32 q-114.5 32 -214 90 q-99.5 58 -181 139.5 q-81.5 81.5 -140 180.5 q-58.5 99 -90.5 213.5 q-32 114.5 -32 237.5 q0 65 8 120 q8 55 23 107.5 q15 52.5 36 104.5 q21 52 48 109 q8 16 8 31 q0 11 -6 41 q-6 30 -16 69 q-10 39 -21.5 84 q-11.5 45 -22.5 86 q-11 41 -20 74.5 q-9 33.5 -13 49.5 q68 -16 134.5 -32 q66.5 -16 134.5 -33 q34 -8 71 -19 q37 -11 72 -11 q8 0 15 2.5 q7 2.5 15 5.5 q54 25 104.5 45.5 q50.5 20.5 101.5 34.5 q51 14 105 22 q54 8 115 8 ZM704 896 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 l640 0 q26 0 45 19 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 l-640 0 ZM704 1280 q-26 0 -45 -19 q-19 -19 -19 -45 q0 -26 19 -45 q19 -19 45 -19 l384 0 q26 0 45 19 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 l-384 0 Z"/></svg>
\ No newline at end of file
<svg width="98" height="96" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#24292f"/></svg>
\ No newline at end of file
<svg width="98" height="96" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#fff"/></svg>
\ No newline at end of file
GalleryInterface,
ToolBar,
#view {
background-color: transparent;
}
QScrollArea {
border: none;
}
ToolBar > #titleLabel {
font: 28px 'Segoe UI SemiBold', 'Microsoft YaHei';
font-weight: bold;
background-color: transparent;
color: white;
}
ToolBar > #subtitleLabel {
font: 12px 'Segoe UI', 'Microsoft YaHei';
background-color: transparent;
color: white;
}
ExampleCard {
background-color: transparent;
}
ExampleCard>#card {
border: 1px solid rgb(32, 32, 32);
border-radius: 10px;
background-color: rgb(36, 36, 36);
}
ExampleCard>#titleLabel {
font: 14px 'Segoe UI SemiBold', 'Microsoft YaHei';
background-color: transparent;
color: white;
}
#sourceWidget {
background-color: rgb(51, 51, 51);
border-top: 1px solid rgb(36, 36, 36);
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}
#sourcePathLabel {
color: white;
font: 14px 'Segoe UI', 'Microsoft YaHei';
}
QScrollBar {
background: transparent;
width: 4px;
margin-top: 32px;
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
StackedWidget {
border: 1px solid rgb(29, 29, 29);
border-right: none;
border-bottom: none;
border-top-left-radius: 10px;
background-color: rgb(39, 39, 39);
}
MainWindow {
background-color: rgb(32, 32, 32);
}
CustomTitleBar {
background-color: transparent;
}
CustomTitleBar > QLabel,
Widget > QLabel {
color: white;
}
CustomTitleBar>QLabel#titleLabel {
background: transparent;
font: 13px 'Segoe UI';
padding: 0 4px
}
MinimizeButton {
qproperty-normalColor: white;
qproperty-normalBackgroundColor: transparent;
qproperty-hoverColor: white;
qproperty-hoverBackgroundColor: rgba(255, 255, 255, 26);
qproperty-pressedColor: white;
qproperty-pressedBackgroundColor: rgba(255, 255, 255, 51)
}
MaximizeButton {
qproperty-normalColor: white;
qproperty-normalBackgroundColor: transparent;
qproperty-hoverColor: white;
qproperty-hoverBackgroundColor: rgba(255, 255, 255, 26);
qproperty-pressedColor: white;
qproperty-pressedBackgroundColor: rgba(255, 255, 255, 51)
}
CloseButton {
qproperty-normalColor: white;
qproperty-normalBackgroundColor: transparent;
}
SettingInterface, #scrollWidget {
background-color: transparent;
}
QScrollArea {
border: none;
background-color: transparent;
}
/* 标签 */
QLabel#settingLabel {
font: 33px 'Microsoft YaHei Light';
background-color: transparent;
color: white;
}
/* 滚动条 */
QScrollBar {
background: transparent;
width: 4px;
margin-top: 32px;
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
GalleryInterface, ToolBar, #view {
background-color: transparent;
}
QScrollArea {
border: none;
}
ToolBar > #titleLabel {
font: 28px 'Segoe UI SemiBold', 'Microsoft YaHei';
background-color: transparent;
color: black;
}
ToolBar > #subtitleLabel {
font: 12px 'Segoe UI', 'Microsoft YaHei';
background-color: transparent;
color: rgb(95, 95, 95);
}
ExampleCard {
background-color: transparent;
}
ExampleCard > #card {
border: 1px solid rgb(234, 234, 234);
border-radius: 10px;
background-color: rgb(243, 243, 243);
}
ExampleCard > #titleLabel {
font: 14px 'Segoe UI SemiBold', 'Microsoft YaHei';
background-color: transparent;
color: black;
}
#sourceWidget {
background-color: rgb(253, 253, 253);
border-top: 1px solid rgb(234, 234, 234);
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}
#sourcePathLabel {
color: black;
font: 14px 'Segoe UI', 'Microsoft YaHei';
}
QScrollBar {
background: transparent;
width: 4px;
margin-top: 32px;
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
StackedWidget {
border: 1px solid rgb(229, 229, 229);
border-right: none;
border-bottom: none;
border-top-left-radius: 10px;
background-color: rgb(249, 249, 249);
}
MainWindow {
background-color: rgb(243, 243, 243);
}
CustomTitleBar > QLabel#titleLabel {
color: black;
background: transparent;
font: 13px 'Segoe UI';
padding: 0 4px
}
MinimizeButton {
qproperty-normalColor: black;
qproperty-normalBackgroundColor: transparent;
qproperty-hoverColor: black;
qproperty-hoverBackgroundColor: rgba(0, 0, 0, 26);
qproperty-pressedColor: black;
qproperty-pressedBackgroundColor: rgba(0, 0, 0, 51)
}
MaximizeButton {
qproperty-normalColor: black;
qproperty-normalBackgroundColor: transparent;
qproperty-hoverColor: black;
qproperty-hoverBackgroundColor: rgba(0, 0, 0, 26);
qproperty-pressedColor: black;
qproperty-pressedBackgroundColor: rgba(0, 0, 0, 51)
}
CloseButton {
qproperty-normalColor: black;
qproperty-normalBackgroundColor: transparent;
}
\ No newline at end of file
SettingInterface, #scrollWidget {
background-color: transparent;
}
QScrollArea {
background-color: transparent;
border: none;
}
/* 标签 */
QLabel#settingLabel {
font: 33px 'Microsoft YaHei Light';
background-color: transparent;
}
/* 滚动条 */
QScrollBar {
background: transparent;
width: 4px;
margin-top: 32px;
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 PyQt5.QtCore import Qt, QSize
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QButtonGroup
from PyQt5.QtMultimedia import QSound
from qfluentwidgets import (PushButton, ToolButton, PrimaryPushButton, HyperlinkButton,
ComboBox, RadioButton, CheckBox, Slider)
from .gallery_interface import GalleryInterface
from ..common.translator import Translator
class BasicInputInterface(GalleryInterface):
""" Basic input interface """
def __init__(self, parent=None):
translator = Translator()
super().__init__(
title=translator.basicInput,
subtitle='qfluentwidgets.components.widgets',
parent=parent
)
self.addExampleCard(
self.tr('A simple button with text content'),
PushButton('Standard push button'),
'https://github.com/zhiyiYo/PyQt-Fluent-Widgets/blob/master/examples/button/demo.py'
)
button = ToolButton('app/resource/images/kunkun.png')
button.setIconSize(QSize(40, 40))
button.clicked.connect(lambda: QSound.play(
'app/resource/audio/ZhiYinJi.wav'))
button.resize(70, 70)
self.addExampleCard(
self.tr('A button with graphical content'),
button,
'https://github.com/zhiyiYo/PyQt-Fluent-Widgets/blob/master/examples/button/demo.py'
)
self.addExampleCard(
self.tr('Accent style applied to button'),
PrimaryPushButton('Accent style button'),
'https://github.com/zhiyiYo/PyQt-Fluent-Widgets/blob/master/examples/button/demo.py'
)
self.addExampleCard(
self.tr('A hyperlink button that navigates to a URI'),
HyperlinkButton('http://github.com', 'GitHub home page'),
'https://github.com/zhiyiYo/PyQt-Fluent-Widgets/blob/master/examples/button/demo.py'
)
self.addExampleCard(
self.tr('A 2-state CheckBox'),
CheckBox('Two-state CheckBox'),
'https://github.com/zhiyiYo/PyQt-Fluent-Widgets/blob/master/examples/check_box/demo.py'
)
checkBox = CheckBox('Three-state CheckBox')
checkBox.setTristate(True)
self.addExampleCard(
self.tr('A 3-state CheckBox'),
checkBox,
'https://github.com/zhiyiYo/PyQt-Fluent-Widgets/blob/master/examples/check_box/demo.py'
)
comboBox = ComboBox()
comboBox.addItems(['shoko 🥰', '西宫硝子 😊', '一级棒卡哇伊的硝子酱 😘'])
comboBox.setCurrentIndex(0)
comboBox.setMinimumWidth(210)
self.addExampleCard(
self.tr('A ComboBox with items'),
comboBox,
'https://github.com/zhiyiYo/PyQt-Fluent-Widgets/blob/master/examples/combo_box/demo.py'
)
radioWidget = QWidget()
radioLayout = QVBoxLayout(radioWidget)
radioLayout.setContentsMargins(2, 0, 0, 0)
radioLayout.setSpacing(15)
radioButton1 = RadioButton('Star Platinum', radioWidget)
radioButton2 = RadioButton('Crazy Diamond', radioWidget)
radioButton3 = RadioButton('Soft and Wet', radioWidget)
buttonGroup = QButtonGroup(radioWidget)
buttonGroup.addButton(radioButton1)
buttonGroup.addButton(radioButton2)
buttonGroup.addButton(radioButton3)
radioLayout.addWidget(radioButton1)
radioLayout.addWidget(radioButton2)
radioLayout.addWidget(radioButton3)
self.addExampleCard(
self.tr('A group of RadioButton controls in a button group'),
radioWidget,
'https://github.com/zhiyiYo/PyQt-Fluent-Widgets/blob/master/examples/radio_button/demo.py'
)
slider = Slider(Qt.Horizontal)
slider.setRange(0, 100)
slider.setFixedWidth(200)
self.addExampleCard(
self.tr('A simple horizontal slider'),
slider,
'https://github.com/zhiyiYo/PyQt-Fluent-Widgets/blob/master/examples/slider/demo.py'
)
# coding:utf-8
from PyQt5.QtCore import Qt, pyqtSignal, QUrl, QEvent
from PyQt5.QtGui import QDesktopServices
from PyQt5.QtWidgets import QWidget, QLabel, QVBoxLayout, QHBoxLayout, QFrame
from qfluentwidgets import (ScrollArea, PushButton, ToolButton, FluentIcon,
isDarkTheme, IconWidget, Theme)
from ..common.icon import Icon
from ..common.config import cfg, FEEDBACK_URL, DOCUMENT_URL, EXAMPLE_URL
class ToolBar(QWidget):
""" Tool bar """
def __init__(self, title, subtitle, parent=None):
super().__init__(parent=parent)
self.titleLabel = QLabel(title, self)
self.subtitleLabel = QLabel(subtitle, self)
self.documentButton = PushButton(
self.tr('Documentation'), self, Icon.DOCUMENT)
self.sourceButton = PushButton(self.tr('Source'), self, Icon.GITHUB)
self.themeButton = ToolButton(Icon.CONSTRACT, self)
self.feedbackButton = ToolButton(FluentIcon.FEEDBACK, self)
self.vBoxLayout = QVBoxLayout(self)
self.buttonLayout = QHBoxLayout()
self.__initWidget()
def __initWidget(self):
self.setFixedHeight(138)
self.vBoxLayout.setSpacing(0)
self.vBoxLayout.setContentsMargins(36, 22, 36, 12)
self.vBoxLayout.addWidget(self.titleLabel)
self.vBoxLayout.addSpacing(4)
self.vBoxLayout.addWidget(self.subtitleLabel)
self.vBoxLayout.addSpacing(4)
self.vBoxLayout.addLayout(self.buttonLayout, 1)
self.vBoxLayout.setAlignment(Qt.AlignTop)
self.buttonLayout.setSpacing(4)
self.buttonLayout.setContentsMargins(0, 0, 0, 0)
self.buttonLayout.addWidget(self.documentButton, 0, Qt.AlignLeft)
self.buttonLayout.addWidget(self.sourceButton, 0, Qt.AlignLeft)
self.buttonLayout.addStretch(1)
self.buttonLayout.addWidget(self.themeButton, 0, Qt.AlignRight)
self.buttonLayout.addWidget(self.feedbackButton, 0, Qt.AlignRight)
self.buttonLayout.setAlignment(Qt.AlignVCenter | Qt.AlignLeft)
self.titleLabel.setObjectName('titleLabel')
self.subtitleLabel.setObjectName('subtitleLabel')
self.themeButton.clicked.connect(self.toggleTheme)
self.documentButton.clicked.connect(
lambda: QDesktopServices.openUrl(QUrl(DOCUMENT_URL)))
self.sourceButton.clicked.connect(
lambda: QDesktopServices.openUrl(QUrl(EXAMPLE_URL)))
self.feedbackButton.clicked.connect(
lambda: QDesktopServices.openUrl(QUrl(FEEDBACK_URL)))
def toggleTheme(self):
theme = Theme.LIGHT if isDarkTheme() else Theme.DARK
cfg.set(cfg.themeMode, theme)
class ExampleCard(QWidget):
""" Example card """
def __init__(self, title, widget: QWidget, sourcePath, parent=None):
super().__init__(parent=parent)
self.widget = widget
self.titleLabel = QLabel(title, self)
self.card = QFrame(self)
self.sourceWidget = QFrame(self.card)
self.sourcePath = sourcePath
self.sourcePathLabel = QLabel(self.tr('Source code'), self.sourceWidget)
self.linkIcon = IconWidget(FluentIcon.LINK, self.sourceWidget)
self.vBoxLayout = QVBoxLayout(self)
self.cardLayout = QVBoxLayout(self.card)
self.topLayout = QHBoxLayout()
self.bottomLayout = QHBoxLayout(self.sourceWidget)
self.__initWidget()
def __initWidget(self):
self.linkIcon.setFixedSize(16, 16)
self.__initLayout()
self.sourceWidget.setCursor(Qt.PointingHandCursor)
self.sourceWidget.installEventFilter(self)
self.titleLabel.setObjectName('titleLabel')
self.card.setObjectName('card')
self.sourcePathLabel.setObjectName('sourcePathLabel')
self.sourceWidget.setObjectName('sourceWidget')
def __initLayout(self):
self.vBoxLayout.setSizeConstraint(QVBoxLayout.SetMinimumSize)
self.cardLayout.setSizeConstraint(QVBoxLayout.SetMinimumSize)
self.topLayout.setSizeConstraint(QHBoxLayout.SetMinimumSize)
self.vBoxLayout.setSpacing(12)
self.vBoxLayout.setContentsMargins(0, 0, 0, 0)
self.topLayout.setContentsMargins(12, 12, 12, 12)
self.bottomLayout.setContentsMargins(18, 18, 18, 18)
self.cardLayout.setContentsMargins(0, 0, 0, 0)
self.vBoxLayout.addWidget(self.titleLabel, 0, Qt.AlignTop)
self.vBoxLayout.addWidget(self.card, 0, Qt.AlignTop)
self.vBoxLayout.setAlignment(Qt.AlignTop)
self.cardLayout.setSpacing(0)
self.cardLayout.setAlignment(Qt.AlignTop)
self.cardLayout.addLayout(self.topLayout, 0)
self.cardLayout.addWidget(self.sourceWidget, 0, Qt.AlignBottom)
self.widget.setParent(self.card)
self.topLayout.addWidget(self.widget)
self.topLayout.addStretch(1)
self.widget.show()
self.bottomLayout.addWidget(self.sourcePathLabel, 0, Qt.AlignLeft)
self.bottomLayout.addStretch(1)
self.bottomLayout.addWidget(self.linkIcon, 0, Qt.AlignRight)
self.bottomLayout.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
def eventFilter(self, obj, e):
if obj is self.sourceWidget:
if e.type() == QEvent.MouseButtonRelease:
QDesktopServices.openUrl(QUrl(self.sourcePath))
return super().eventFilter(obj, e)
class GalleryInterface(ScrollArea):
""" Gallery interface """
def __init__(self, title: str, subtitle: str, parent=None):
super().__init__(parent=parent)
self.view = QWidget(self)
self.toolBar = ToolBar(title, subtitle, self)
self.vBoxLayout = QVBoxLayout(self.view)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setViewportMargins(0, self.toolBar.height(), 0, 0)
self.setWidget(self.view)
self.setWidgetResizable(True)
self.vBoxLayout.setSpacing(30)
self.vBoxLayout.setAlignment(Qt.AlignTop)
self.vBoxLayout.setContentsMargins(36, 20, 36, 36)
self.__setQss()
cfg.themeChanged.connect(self.__setQss)
def addExampleCard(self, title, widget, sourcePath: str):
card = ExampleCard(title, widget, sourcePath, self.view)
self.vBoxLayout.addWidget(card, 0, Qt.AlignTop)
def resizeEvent(self, e):
super().resizeEvent(e)
self.toolBar.resize(self.width(), self.toolBar.height())
def __setQss(self):
self.view.setObjectName('view')
theme = 'dark' if isDarkTheme() else 'light'
with open(f'app/resource/qss/{theme}/gallery_interface.qss', encoding='utf-8') as f:
self.setStyleSheet(f.read())
# coding: utf-8
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QStackedWidget, QHBoxLayout, QFrame, QWidget
from qfluentwidgets import (NavigationInterface, NavigationItemPostion, MessageBox,
isDarkTheme)
from qfluentwidgets import FluentIcon as FIF
from qframelesswindow import FramelessWindow
from .title_bar import CustomTitleBar
from .setting_interface import SettingInterface, cfg
from .basic_input_interface import BasicInputInterface
from ..components.avatar_widget import AvatarWidget
from ..common.icon import Icon
class StackedWidget(QFrame):
""" Stacked widget """
currentWidgetChanged = pyqtSignal(QWidget)
def __init__(self, parent=None):
super().__init__(parent=parent)
self.hBoxLayout = QHBoxLayout(self)
self.view = QStackedWidget(self)
self.hBoxLayout.setContentsMargins(0, 0, 0, 0)
self.hBoxLayout.addWidget(self.view)
self.view.currentChanged.connect(
lambda i: self.currentWidgetChanged.emit(self.view.widget(i)))
def addWidget(self, widget):
""" add widget to view """
self.view.addWidget(widget)
def setCurrentWidget(self, widget):
self.view.setCurrentWidget(widget)
def setCurrentIndex(self, index):
self.view.setCurrentIndex(index)
class MainWindow(FramelessWindow):
def __init__(self):
super().__init__()
self.setTitleBar(CustomTitleBar(self))
self.hBoxLayout = QHBoxLayout(self)
self.widgetLayout = QHBoxLayout()
self.stackWidget = StackedWidget(self)
self.navigationInterface = NavigationInterface(self, True, True)
# create sub interface
self.basicInputInterface = BasicInputInterface(self)
self.settingInterface = SettingInterface(self)
self.stackWidget.addWidget(self.basicInputInterface)
self.stackWidget.addWidget(self.settingInterface)
# initialize layout
self.initLayout()
# add items to navigation interface
self.initNavigation()
self.initWindow()
def initLayout(self):
self.hBoxLayout.setSpacing(0)
self.hBoxLayout.setContentsMargins(0, 0, 0, 0)
self.hBoxLayout.addWidget(self.navigationInterface)
self.hBoxLayout.addLayout(self.widgetLayout)
self.hBoxLayout.setStretchFactor(self.widgetLayout, 1)
self.widgetLayout.addWidget(self.stackWidget)
self.widgetLayout.setContentsMargins(0, 48, 0, 0)
self.navigationInterface.displayModeChanged.connect(
self.titleBar.raise_)
self.titleBar.raise_()
def initNavigation(self):
self.basicInputInterface.setObjectName('basicInterface')
self.settingInterface.setObjectName('settingsInterface')
self.navigationInterface.addItem(
routeKey='Home',
icon=Icon.HOME,
text=self.tr('Home'),
onClick=print
)
self.navigationInterface.addSeparator()
self.navigationInterface.addItem(
routeKey=self.basicInputInterface.objectName(),
icon=Icon.CHECKBOX,
text=self.tr('Basic input'),
onClick=lambda: self.switchTo(self.basicInputInterface),
position=NavigationItemPostion.SCROLL
)
self.navigationInterface.addItem(
routeKey='Dialogs',
icon=Icon.MESSAGE,
text=self.tr('Dialogs'),
onClick=print,
position=NavigationItemPostion.SCROLL
)
self.navigationInterface.addItem(
routeKey='Status&info',
icon=Icon.LAYOUT,
text=self.tr('Layout'),
onClick=print,
position=NavigationItemPostion.SCROLL
)
self.navigationInterface.addItem(
routeKey='Menus',
icon=Icon.MENU,
text=self.tr('Menus'),
onClick=print,
position=NavigationItemPostion.SCROLL
)
self.navigationInterface.addItem(
routeKey='Material',
icon=FIF.PALETTE,
text=self.tr('Material'),
onClick=print,
position=NavigationItemPostion.SCROLL
)
self.navigationInterface.addItem(
routeKey='Layout',
icon=Icon.CHAT,
text=self.tr('Status & info'),
onClick=print,
position=NavigationItemPostion.SCROLL
)
# add custom widget to bottom
self.navigationInterface.addWidget(
routeKey='avatar',
widget=AvatarWidget('app/resource/images/shoko.png'),
onClick=self.showMessageBox,
position=NavigationItemPostion.BOTTOM
)
self.navigationInterface.addItem(
routeKey=self.settingInterface.objectName(),
icon=FIF.SETTING,
text='Settings',
onClick=lambda: self.switchTo(self.settingInterface),
position=NavigationItemPostion.BOTTOM
)
#!IMPORTANT: don't forget to set the default route key if you enable the return button
self.navigationInterface.setDefaultRouteKey(
self.basicInputInterface.objectName())
self.stackWidget.currentWidgetChanged.connect(
lambda w: self.navigationInterface.setCurrentItem(w.objectName()))
self.navigationInterface.setCurrentItem(self.basicInputInterface.objectName())
self.stackWidget.setCurrentIndex(0)
def initWindow(self):
self.resize(900, 700)
self.setWindowIcon(QIcon('app/resource/images/logo.png'))
self.setWindowTitle('PyQt-Fluent-Widgets')
self.titleBar.setAttribute(Qt.WA_StyledBackground)
desktop = QApplication.desktop().availableGeometry()
w, h = desktop.width(), desktop.height()
self.move(w//2 - self.width()//2, h//2 - self.height()//2)
cfg.themeChanged.connect(self.setQss)
self.setQss()
def setQss(self):
color = 'dark' if isDarkTheme() else 'light'
with open(f'app/resource/qss/{color}/main_window.qss', encoding='utf-8') as f:
self.setStyleSheet(f.read())
def switchTo(self, widget):
self.stackWidget.setCurrentWidget(widget)
def resizeEvent(self, e):
self.titleBar.move(46, 0)
self.titleBar.resize(self.width()-46, self.titleBar.height())
def showMessageBox(self):
w = MessageBox(
'This is a help message',
'You clicked a customized navigation widget. You can add more custom widgets by calling `NavigationInterface.addWidget()` 😉',
self
)
w.exec()
# coding:utf-8
from qfluentwidgets import (SettingCardGroup, SwitchSettingCard, FolderListSettingCard,
OptionsSettingCard, PushSettingCard,
HyperlinkCard, PrimaryPushSettingCard, ScrollArea,
ComboBoxSettingCard, ExpandLayout, Theme, ToastToolTip, CustomColorSettingCard,
setTheme, setThemeColor)
from qfluentwidgets import FluentIcon as FIF
from PyQt5.QtCore import Qt, pyqtSignal, QUrl, QStandardPaths
from PyQt5.QtGui import QDesktopServices
from PyQt5.QtWidgets import QWidget, QLabel, QFileDialog
from ..common.config import cfg, HELP_URL, FEEDBACK_URL, AUTHOR, VERSION, YEAR
class SettingInterface(ScrollArea):
""" Setting interface """
checkUpdateSig = pyqtSignal()
musicFoldersChanged = pyqtSignal(list)
acrylicEnableChanged = pyqtSignal(bool)
downloadFolderChanged = pyqtSignal(str)
minimizeToTrayChanged = pyqtSignal(bool)
def __init__(self, parent=None):
super().__init__(parent=parent)
self.scrollWidget = QWidget()
self.expandLayout = ExpandLayout(self.scrollWidget)
# setting label
self.settingLabel = QLabel(self.tr("Settings"), self)
# music folders
self.musicInThisPCGroup = SettingCardGroup(
self.tr("Music on this PC"), self.scrollWidget)
self.musicFolderCard = FolderListSettingCard(
cfg.musicFolders,
self.tr("Local music library"),
directory=QStandardPaths.writableLocation(QStandardPaths.MusicLocation),
parent=self.musicInThisPCGroup
)
self.downloadFolderCard = PushSettingCard(
self.tr('Choose folder'),
FIF.DOWNLOAD,
self.tr("Download directory"),
cfg.get(cfg.downloadFolder),
self.musicInThisPCGroup
)
# personalization
self.personalGroup = SettingCardGroup(self.tr('Personalization'), self.scrollWidget)
self.themeCard = OptionsSettingCard(
cfg.themeMode,
FIF.BRUSH,
self.tr('Application theme'),
self.tr("Change the appearance of your application"),
texts=[
self.tr('Light'), self.tr('Dark'),
self.tr('Use system setting')
],
parent=self.personalGroup
)
self.themeColorCard=CustomColorSettingCard(
cfg.themeColor,
FIF.PALETTE,
self.tr('Theme color'),
self.tr('Change the theme color of you application'),
self.personalGroup
)
self.zoomCard = OptionsSettingCard(
cfg.dpiScale,
FIF.ZOOM,
self.tr("Interface zoom"),
self.tr("Change the size of widgets and fonts"),
texts=[
"100%", "125%", "150%", "175%", "200%",
self.tr("Use system setting")
],
parent=self.personalGroup
)
self.languageCard = ComboBoxSettingCard(
cfg.language,
FIF.LANGUAGE,
self.tr('Language'),
self.tr('Set your preferred language for UI'),
texts=['简体中文', '繁體中文', 'English', self.tr('Use system setting')],
parent=self.personalGroup
)
# update software
self.updateSoftwareGroup = SettingCardGroup(self.tr("Software update"), self.scrollWidget)
self.updateOnStartUpCard = SwitchSettingCard(
FIF.UPDATE,
self.tr('Check for updates when the application starts'),
self.tr('The new version will be more stable and have more features'),
configItem=cfg.checkUpdateAtStartUp,
parent=self.updateSoftwareGroup
)
# application
self.aboutGroup = SettingCardGroup(self.tr('About'), self.scrollWidget)
self.helpCard = HyperlinkCard(
HELP_URL,
self.tr('Open help page'),
FIF.HELP,
self.tr('Help'),
self.tr('Discover new features and learn useful tips about PyQt-Fluent-Widgets'),
self.aboutGroup
)
self.feedbackCard = PrimaryPushSettingCard(
self.tr('Provide feedback'),
FIF.FEEDBACK,
self.tr('Provide feedback'),
self.tr('Help us improve PyQt-Fluent-Widgets by providing feedback'),
self.aboutGroup
)
self.aboutCard = PrimaryPushSettingCard(
self.tr('Check update'),
FIF.INFO,
self.tr('About'),
'© ' + self.tr('Copyright') + f" {YEAR}, {AUTHOR}. " +
self.tr('Version') + f" {VERSION[1:]}",
self.aboutGroup
)
self.__initWidget()
def __initWidget(self):
self.resize(1000, 800)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setViewportMargins(0, 80, 0, 20)
self.setWidget(self.scrollWidget)
self.setWidgetResizable(True)
# initialize style sheet
self.__setQss(cfg.theme)
# initialize layout
self.__initLayout()
self.__connectSignalToSlot()
def __initLayout(self):
self.settingLabel.move(36, 30)
# add cards to group
self.musicInThisPCGroup.addSettingCard(self.musicFolderCard)
self.musicInThisPCGroup.addSettingCard(self.downloadFolderCard)
self.personalGroup.addSettingCard(self.themeCard)
self.personalGroup.addSettingCard(self.themeColorCard)
self.personalGroup.addSettingCard(self.zoomCard)
self.personalGroup.addSettingCard(self.languageCard)
self.updateSoftwareGroup.addSettingCard(self.updateOnStartUpCard)
self.aboutGroup.addSettingCard(self.helpCard)
self.aboutGroup.addSettingCard(self.feedbackCard)
self.aboutGroup.addSettingCard(self.aboutCard)
# add setting card group to layout
self.expandLayout.setSpacing(28)
self.expandLayout.setContentsMargins(36, 10, 36, 0)
self.expandLayout.addWidget(self.musicInThisPCGroup)
self.expandLayout.addWidget(self.personalGroup)
self.expandLayout.addWidget(self.updateSoftwareGroup)
self.expandLayout.addWidget(self.aboutGroup)
def __setQss(self, theme: Theme):
""" set style sheet """
self.scrollWidget.setObjectName('scrollWidget')
self.settingLabel.setObjectName('settingLabel')
theme = 'dark' if theme == Theme.DARK else 'light'
with open(f'app/resource/qss/{theme}/setting_interface.qss', encoding='utf-8') as f:
self.setStyleSheet(f.read())
def __showRestartTooltip(self):
""" show restart tooltip """
ToastToolTip.warn(
self.tr('Configuration updated successfully'),
self.tr('Configuration takes effect after restart'),
self.window()
)
def __onDownloadFolderCardClicked(self):
""" download folder card clicked slot """
folder = QFileDialog.getExistingDirectory(
self, self.tr("Choose folder"), "./")
if not folder or cfg.get(cfg.downloadFolder) == folder:
return
cfg.set(cfg.downloadFolder, folder)
self.downloadFolderCard.setContent(folder)
def __onThemeChanged(self, theme: Theme):
""" theme changed slot """
# change the theme of qfluentwidgets
setTheme(theme)
# chang the theme of setting interface
self.__setQss(theme)
def __connectSignalToSlot(self):
""" connect signal to slot """
cfg.appRestartSig.connect(self.__showRestartTooltip)
cfg.themeChanged.connect(self.__onThemeChanged)
# music in the pc
self.musicFolderCard.folderChanged.connect(
self.musicFoldersChanged)
self.downloadFolderCard.clicked.connect(
self.__onDownloadFolderCardClicked)
# personalization
self.themeColorCard.colorChanged.connect(setThemeColor)
# about
self.aboutCard.clicked.connect(self.checkUpdateSig)
self.feedbackCard.clicked.connect(
lambda: QDesktopServices.openUrl(QUrl(FEEDBACK_URL)))
# coding: utf-8
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QLabel
from qframelesswindow import TitleBar
class CustomTitleBar(TitleBar):
""" Title bar with icon and title """
def __init__(self, parent):
super().__init__(parent)
# add window icon
self.iconLabel = QLabel(self)
self.iconLabel.setFixedSize(18, 18)
self.hBoxLayout.insertSpacing(0, 10)
self.hBoxLayout.insertWidget(1, self.iconLabel, 0, Qt.AlignLeft | Qt.AlignBottom)
self.window().windowIconChanged.connect(self.setIcon)
# add title label
self.titleLabel = QLabel(self)
self.hBoxLayout.insertWidget(2, self.titleLabel, 0, Qt.AlignLeft | Qt.AlignBottom)
self.titleLabel.setObjectName('titleLabel')
self.window().windowTitleChanged.connect(self.setTitle)
def setTitle(self, title):
self.titleLabel.setText(title)
self.titleLabel.adjustSize()
def setIcon(self, icon):
self.iconLabel.setPixmap(QIcon(icon).pixmap(18, 18))
# coding:utf-8
import os
import sys
from PyQt5.QtCore import Qt, QLocale, QTranslator
from PyQt5.QtWidgets import QApplication
from app.common.config import cfg, Language
from app.view.main_window import MainWindow
# enable dpi scale
if cfg.get(cfg.dpiScale) == "Auto":
QApplication.setHighDpiScaleFactorRoundingPolicy(
Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
else:
os.environ["QT_ENABLE_HIGHDPI_SCALING"] = "0"
os.environ["QT_SCALE_FACTOR"] = str(cfg.get(cfg.dpiScale))
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
# create application
app = QApplication(sys.argv)
app.setAttribute(Qt.AA_DontCreateNativeWidgetSiblings)
# internationalization
translator = QTranslator()
language = cfg.get(cfg.language)
if language == Language.AUTO:
translator.load(QLocale.system(), "app/resource/i18n/qfluentwidgets_")
elif language != Language.ENGLISH:
translator.load(f"app/resource/i18n/qfluentwidgets_{language.value}.qm")
app.installTranslator(translator)
# create main window
w = MainWindow()
w.show()
app.exec_()
\ No newline at end of file
......@@ -155,9 +155,11 @@ class ColorSerializer(ConfigSerializer):
return QColor(value)
class ConfigItem:
class ConfigItem(QObject):
""" Config item """
valueChanged = pyqtSignal(object)
def __init__(self, group, name, default, validator=None, serializer=None, restart=False):
"""
Parameters
......@@ -180,6 +182,7 @@ class ConfigItem:
restart: bool
whether to restart the application after updating value
"""
super().__init__()
self.group = group
self.name = name
self.validator = validator or ConfigValidator()
......@@ -196,7 +199,11 @@ class ConfigItem:
@value.setter
def value(self, v):
self.__value = self.validator.correct(v)
v = self.validator.correct(v)
ov = self.__value
self.__value = v
if ov != v:
self.valueChanged.emit(v)
@property
def key(self):
......
......@@ -199,6 +199,10 @@ class ExpandSettingCard(QFrame):
if self.view.isVisible():
self.resize(self.width(), h + self.card.height())
def setValue(self, value):
""" set the value of config item """
pass
class GroupSeparator(QWidget):
......
......@@ -56,7 +56,8 @@ class OptionsSettingCard(ExpandSettingCard):
button.setProperty(self.configName, option)
self._adjustViewSize()
self.setSelected(qconfig.get(self.configItem))
self.setValue(qconfig.get(self.configItem))
configItem.valueChanged.connect(self.setValue)
self.buttonGroup.buttonClicked.connect(self.__onButtonClicked)
def __onButtonClicked(self, button: RadioButton):
......@@ -71,11 +72,14 @@ class OptionsSettingCard(ExpandSettingCard):
self.choiceLabel.adjustSize()
self.optionChanged.emit(self.configItem)
def setSelected(self, value):
def setValue(self, value):
""" select button according to the value """
qconfig.set(self.configItem, value)
for button in self.viewLayout.widgets:
isChecked = button.property(self.configName) == value
button.setChecked(isChecked)
if isChecked:
self.choiceLabel.setText(button.text())
self.choiceLabel.adjustSize()
# coding:utf-8
from typing import Union
from PyQt5.QtCore import QUrl, Qt, pyqtSignal
from PyQt5.QtGui import QColor, QDesktopServices, QIcon, QPainter
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QColor, QIcon, QPainter
from PyQt5.QtWidgets import (QFrame, QHBoxLayout, QLabel, QToolButton,
QVBoxLayout, QPushButton)
......@@ -13,7 +13,7 @@ from ..widgets.slider import Slider
from ..widgets.icon_widget import IconWidget
from ..widgets.button import HyperlinkButton
from ...common.style_sheet import setStyleSheet
from ...common.config import qconfig, isDarkTheme
from ...common.config import qconfig, isDarkTheme, ConfigItem
from ...common.icon import FluentIconBase
......@@ -79,13 +79,18 @@ class SettingCard(QFrame):
self.contentLabel.setText(content)
self.contentLabel.setVisible(bool(content))
def setValue(self, value):
""" set the value of config item """
pass
class SwitchSettingCard(SettingCard):
""" Setting card with switch button """
checkedChanged = pyqtSignal(bool)
def __init__(self, icon: Union[str, QIcon, FluentIconBase], title, content=None, configItem=None, parent=None):
def __init__(self, icon: Union[str, QIcon, FluentIconBase], title, content=None,
configItem: ConfigItem = None, parent=None):
"""
Parameters
----------
......@@ -110,7 +115,8 @@ class SwitchSettingCard(SettingCard):
self.tr('Off'), self, IndicatorPosition.RIGHT)
if configItem:
self.setChecked(qconfig.get(configItem))
self.setValue(qconfig.get(configItem))
configItem.valueChanged.connect(self.setValue)
# add switch button to layout
self.hBoxLayout.addWidget(self.switchButton, 0, Qt.AlignRight)
......@@ -120,11 +126,10 @@ class SwitchSettingCard(SettingCard):
def __onCheckedChanged(self, isChecked: bool):
""" switch button checked state changed slot """
self.setChecked(isChecked)
self.setValue(isChecked)
self.checkedChanged.emit(isChecked)
def setChecked(self, isChecked: bool):
""" set switch button checked state """
def setValue(self, isChecked: bool):
if self.configItem:
qconfig.set(self.configItem, isChecked)
......@@ -177,14 +182,18 @@ class RangeSettingCard(SettingCard):
self.hBoxLayout.addSpacing(16)
self.valueLabel.setObjectName('valueLabel')
configItem.valueChanged.connect(self.setValue)
self.slider.valueChanged.connect(self.__onValueChanged)
def __onValueChanged(self, value: int):
""" slider value changed slot """
self.setValue(value)
self.valueChanged.emit(value)
def setValue(self, value):
qconfig.set(self.configItem, value)
self.valueLabel.setNum(value)
self.valueLabel.adjustSize()
self.valueChanged.emit(value)
class PushSettingCard(SettingCard):
......@@ -333,11 +342,16 @@ class ColorSettingCard(SettingCard):
self.hBoxLayout.addWidget(self.colorPicker, 0, Qt.AlignRight)
self.hBoxLayout.addSpacing(16)
self.colorPicker.colorChanged.connect(self.__onColorChanged)
configItem.valueChanged.connect(self.setValue)
def __onColorChanged(self, color: QColor):
qconfig.set(self.configItem, color)
self.colorChanged.emit(color)
def setValue(self, color: QColor):
self.colorPicker.setColor(color)
qconfig.set(self.configItem, color)
class ComboBoxSettingCard(SettingCard):
""" Setting card with a combo box """
......@@ -375,6 +389,11 @@ class ComboBoxSettingCard(SettingCard):
self.comboBox.addItems(texts)
self.comboBox.setCurrentText(self.optionToText[qconfig.get(configItem)])
self.comboBox.currentTextChanged.connect(self._onCurrentTextChanged)
configItem.valueChanged.connect(self.setValue)
def _onCurrentTextChanged(self, text):
qconfig.set(self.configItem, self.textToOption[text])
def setValue(self, text):
self.comboBox.setCurrentText(text)
qconfig.set(self.configItem, self.textToOption[text])
\ No newline at end of file
......@@ -8,4 +8,5 @@ from .scroll_area import ScrollArea, SmoothMode, SmoothScrollArea, SmoothScrollB
from .tool_tip import ToolTip, ToolTipFilter
from .button import PrimaryPushButton, PushButton, RadioButton, HyperlinkButton, ToolButton
from .line_edit import LineEdit
from .check_box import CheckBox
\ No newline at end of file
from .check_box import CheckBox
from .icon_widget import IconWidget
\ No newline at end of file
......@@ -16,6 +16,7 @@ class LineEdit(QLineEdit):
setStyleSheet(self, 'line_edit')
self.setFixedHeight(33)
self.setAttribute(Qt.WA_MacShowFocusRect, False)
self.clearButton = QToolButton(self)
self.setTextMargins(0, 0, 33, 0)
......
......@@ -563,8 +563,8 @@ class RoundMenu(QWidget):
rect = QApplication.screenAt(QCursor.pos()).availableGeometry()
w, h = self.width() + 5, self.height() + 5
pos.setX(max(10, min(pos.x() - self.layout().contentsMargins().left(), rect.right() - w)))
pos.setY(max(10, min(pos.y() - 4, rect.bottom() - h)))
pos.setX(min(pos.x() - self.layout().contentsMargins().left(), rect.right() - w))
pos.setY(min(pos.y() - 4, rect.bottom() - h))
if ani:
self.ani.setStartValue(pos-QPoint(0, int(h/2)))
......
......@@ -52,8 +52,9 @@ class Indicator(QToolButton):
return
super().setChecked(isChecked)
self.sliderRadius = (self.height()-2*self.padding)//2
self.sliderEndX = self.width()-2*self.sliderRadius - \
self.padding if self.isChecked() else self.padding
self.padding if isChecked else self.padding
self.timer.start(5)
def mouseReleaseEvent(self, e):
......
......@@ -93,7 +93,7 @@ class ToolTip(QFrame):
# adjust postion to prevent tooltips from appearing outside the screen
rect = QApplication.screenAt(QCursor.pos()).availableGeometry()
x = min(max(0, x), rect.width() - self.width() - 4)
x = min(max(0, x) if QCursor().pos().x() >= 0 else x, rect.width() - self.width() - 4)
y = min(max(0, y), rect.height() - self.height() - 4)
self.move(x, y)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册