├── .gitattributes
├── .github
└── workflows
│ └── ruff.yml
├── .gitignore
├── LICENSE
├── README.md
├── assets
└── readme
│ └── silicon_main.png
├── docs
├── README_zh.md
├── coding_standard.md
└── template
│ └── layer.md
├── examples
├── Gallery for siui
│ ├── __init__.py
│ ├── components
│ │ ├── __init__.py
│ │ ├── option_card
│ │ │ ├── __init__.py
│ │ │ └── plane.py
│ │ ├── page_about
│ │ │ ├── __init__.py
│ │ │ └── page_about.py
│ │ ├── page_container
│ │ │ ├── __init__.py
│ │ │ └── page_container.py
│ │ ├── page_dialog
│ │ │ ├── __init__.py
│ │ │ ├── components
│ │ │ │ ├── __init__.py
│ │ │ │ ├── child_page_example.py
│ │ │ │ ├── modal_dialog_example.py
│ │ │ │ └── side_msg_box.py
│ │ │ └── page_dialog.py
│ │ ├── page_functional
│ │ │ ├── __init__.py
│ │ │ ├── components
│ │ │ │ ├── __init__.py
│ │ │ │ └── music_displayer
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ └── music_displayer.py
│ │ │ └── page_functional.py
│ │ ├── page_homepage
│ │ │ ├── __init__.py
│ │ │ ├── components
│ │ │ │ ├── __init__.py
│ │ │ │ └── themed_option_card.py
│ │ │ └── page_homepage.py
│ │ ├── page_icons
│ │ │ ├── __init__.py
│ │ │ └── page_icons.py
│ │ ├── page_option_cards
│ │ │ ├── __init__.py
│ │ │ └── page_option_cards.py
│ │ ├── page_page_control
│ │ │ ├── __init__.py
│ │ │ └── page_control.py
│ │ ├── page_refactor
│ │ │ ├── __init__.py
│ │ │ └── page_refactor.py
│ │ └── page_widgets
│ │ │ ├── __init__.py
│ │ │ ├── components
│ │ │ ├── __init__.py
│ │ │ └── demo_tables.py
│ │ │ └── page_widgets.py
│ ├── icons
│ │ ├── __init__.py
│ │ ├── icons.dat
│ │ └── parser.py
│ ├── img
│ │ ├── about_version.png
│ │ ├── avatar1.png
│ │ ├── avatar2.png
│ │ ├── empty_icon.png
│ │ ├── homepage_background.png
│ │ ├── logo.png
│ │ ├── logo_new.png
│ │ ├── pages
│ │ │ └── functional
│ │ │ │ └── music_covers
│ │ │ │ ├── cover1.jpg
│ │ │ │ ├── cover2.png
│ │ │ │ ├── cover3.png
│ │ │ │ ├── cover4.png
│ │ │ │ ├── cover5.png
│ │ │ │ └── cover6.png
│ │ └── table
│ │ │ ├── flags
│ │ │ ├── CN.png
│ │ │ ├── GB.png
│ │ │ └── UM.png
│ │ │ └── ranks
│ │ │ ├── rank_s.png
│ │ │ └── rank_ss.png
│ ├── start.py
│ ├── test_new_button.py
│ └── ui.py
├── My-TODOs
│ ├── components
│ │ ├── __init__.py
│ │ ├── core.py
│ │ ├── page_about
│ │ │ ├── __init__.py
│ │ │ └── page_about.py
│ │ ├── page_homepage
│ │ │ ├── __init__.py
│ │ │ ├── components
│ │ │ │ ├── __init__.py
│ │ │ │ └── today.py
│ │ │ └── homepage.py
│ │ └── widgets
│ │ │ ├── __init__.py
│ │ │ ├── button.py
│ │ │ ├── group_title.py
│ │ │ └── tasks.py
│ ├── icons
│ │ ├── __init__.py
│ │ ├── icons.dat
│ │ └── parser.py
│ ├── images
│ │ └── default_background.png
│ ├── start.py
│ └── ui.py
└── button
│ └── demo_button.py
├── pyproject.toml
├── setup.py
└── siui
├── __init__.py
├── components
├── __init__.py
├── button.py
├── chart.py
├── combobox
│ ├── __init__.py
│ └── combobox.py
├── container.py
├── editbox.py
├── graphic.py
├── label.py
├── menu
│ ├── __init__.py
│ ├── abstracts
│ │ ├── __init__.py
│ │ ├── ani_manager.py
│ │ └── menu.py
│ ├── menu.py
│ └── option.py
├── menu_.py
├── option_card
│ ├── __init__.py
│ ├── abstracts
│ │ ├── __init__.py
│ │ └── option_card.py
│ └── option_card.py
├── page
│ ├── __init__.py
│ ├── child_page.py
│ └── page.py
├── popover.py
├── progress_bar
│ ├── __init__.py
│ └── progress_bar.py
├── slider
│ ├── __init__.py
│ └── slider.py
├── slider_.py
├── spinbox
│ ├── __init__.py
│ └── spinbox.py
├── titled_widget_group
│ ├── __init__.py
│ └── titled_widget_group.py
├── tooltip
│ ├── __init__.py
│ └── tooltip.py
└── widgets
│ ├── __init__.py
│ ├── abstracts
│ ├── __init__.py
│ ├── button.py
│ ├── container.py
│ ├── label.py
│ ├── line_edit.py
│ ├── navigation_bar.py
│ ├── table.py
│ └── widget.py
│ ├── button.py
│ ├── container.py
│ ├── expands.py
│ ├── label.py
│ ├── line_edit.py
│ ├── navigation_bar.py
│ ├── scrollarea.py
│ ├── table.py
│ ├── timedate.py
│ └── timeline.py
├── core
├── __init__.py
├── alignment.py
├── animation.py
├── color.py
├── effect.py
├── enumrates.py
├── function
│ ├── __init__.py
│ └── chain.py
├── globals.py
├── painter.py
└── token.py
├── gui
├── __init__.py
├── color_group
│ ├── __init__.py
│ ├── bright.py
│ ├── color_group.py
│ └── dark.py
├── font.py
├── icons
│ ├── __init__.py
│ ├── packages
│ │ ├── fluent_ui_icon_filled.icons
│ │ ├── fluent_ui_icon_light.icons
│ │ └── fluent_ui_icon_regular.icons
│ └── parser.py
└── scale.py
├── templates
├── __init__.py
└── application
│ ├── __init__.py
│ ├── application.py
│ └── components
│ ├── __init__.py
│ ├── dialog
│ ├── __init__.py
│ └── modal.py
│ ├── layer
│ ├── __init__.py
│ ├── global_drawer.py
│ ├── layer.py
│ ├── layer_child_page
│ │ ├── __init__.py
│ │ └── layer_child_page.py
│ ├── layer_left_global_drawer
│ │ ├── __init__.py
│ │ └── layer_left_global_drawer.py
│ ├── layer_main
│ │ ├── __init__.py
│ │ └── layer_main.py
│ ├── layer_modal_dialog
│ │ ├── __init__.py
│ │ └── layer_modal_dialog.py
│ ├── layer_overlays
│ │ ├── __init__.py
│ │ └── layer_overlays.py
│ └── layer_right_message_sidebar
│ │ ├── __init__.py
│ │ ├── layer_right_message_sidebar.py
│ │ └── messagebox.py
│ ├── message
│ ├── __init__.py
│ ├── box.py
│ └── sidebar.py
│ └── page_view
│ ├── __init__.py
│ └── page_view.py
└── typing.py
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.github/workflows/ruff.yml:
--------------------------------------------------------------------------------
1 | name: Ruff
2 | on: [ push, pull_request ]
3 | jobs:
4 | ruff:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - uses: actions/checkout@v3
8 | - uses: chartboost/ruff-action@v1
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | share/python-wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 | MANIFEST
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .nox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | *.py,cover
50 | .hypothesis/
51 | .pytest_cache/
52 | cover/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | .pybuilder/
76 | target/
77 |
78 | # Jupyter Notebook
79 | .ipynb_checkpoints
80 |
81 | # IPython
82 | profile_default/
83 | ipython_config.py
84 |
85 | # pyenv
86 | # For a library or package, you might want to ignore these files since the code is
87 | # intended to run in multiple environments; otherwise, check them in:
88 | # .python-version
89 |
90 | # pipenv
91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
94 | # install all needed dependencies.
95 | #Pipfile.lock
96 |
97 | # pdm
98 | .pdm-python
99 |
100 | # poetry
101 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
102 | # This is especially recommended for binary packages to ensure reproducibility, and is more
103 | # commonly ignored for libraries.
104 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
105 | #poetry.lock
106 |
107 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
108 | __pypackages__/
109 |
110 | # Celery stuff
111 | celerybeat-schedule
112 | celerybeat.pid
113 |
114 | # SageMath parsed files
115 | *.sage.py
116 |
117 | # Environments
118 | .env
119 | .venv
120 | env/
121 | venv/
122 | ENV/
123 | env.bak/
124 | venv.bak/
125 |
126 | # Spyder project settings
127 | .spyderproject
128 | .spyproject
129 |
130 | # Rope project settings
131 | .ropeproject
132 |
133 | # mkdocs documentation
134 | /site
135 |
136 | # mypy
137 | .mypy_cache/
138 | .dmypy.json
139 | dmypy.json
140 |
141 | # Pyre type checker
142 | .pyre/
143 |
144 | # pytype static type analyzer
145 | .pytype/
146 |
147 | # Cython debug symbols
148 | cython_debug/
149 |
150 | # PyCharm
151 | # JetBrains specific template is maintainted in a separate JetBrains.gitignore that can
152 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
153 | # and can be added to the globals gitignore or merged into this file. For a more nuclear
154 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
155 | #.idea/
156 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
PyQt-SiliconUI
9 | A powerful and artistic UI library based on PyQt5
10 |
11 |
12 | English | 简体中文
13 |
14 |
15 | ## Install
16 | Download this repository and run setup.py in cmd line:
17 | ```cmd
18 | python setup.py install
19 | ```
20 | Due to the fact that this project is still in the development stage, it is temporarily not available on PyPi.
21 |
22 | However, we are currently working hard on it and will be available soon.
23 |
24 |
25 | ## Run Examples
26 | Run `examples/Gallery for siui/start.py` to take a look at widgets and components of PyQt-SiliconUI
27 |
28 | To quick start, run:
29 | ```cmd
30 | cd "examples/Gallery for siui"
31 | start start.py
32 | ```
33 | Other more detailed examples for widgets are coming soon.
34 |
35 |
36 | ## See Also
37 | Here are some project that created based on PyQt-SiliconUI:
38 | * [My-TODOs](https://github.com/ChinaIceF/My-TODOs) - A cross-platform desktop To-Do list.
39 |
40 |
41 | ## License
42 | PyQt-SiliconUI is licensed under [GPLv3](LICENSE)
43 |
44 | Copyright © 2024 by ChinaIceF.
--------------------------------------------------------------------------------
/assets/readme/silicon_main.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/assets/readme/silicon_main.png
--------------------------------------------------------------------------------
/docs/README_zh.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
PyQt-SiliconUI
9 | 基于 PyQt5 的UI框架,灵动、优雅而轻便
10 |
11 |
12 | English | 简体中文
13 |
14 |
15 | ## 安装
16 | 下载该仓库,在命令行中输入以下命令:
17 | ```cmd
18 | python setup.py install
19 | ```
20 | 由于本项目还在积极开发中,在发布正式版本前不能在 PyPi 上安装,敬请期待。
21 |
22 |
23 | ## 运行示例程序
24 | 运行 `examples/Gallery for siui/start.py` 来体验 PyQt-SiliconUI 提供的控件、组件和框架
25 |
26 | 也可直接在项目目录下运行以下命令:
27 | ```cmd
28 | cd "examples/Gallery for siui"
29 | start start.py
30 | ```
31 | 其他针对各类控件的详细实例将逐一编写
32 |
33 |
34 | ## 另请参阅
35 | 一些基于 PyQt-SiliconUI 编写的项目:
36 | * [My-TODOs](https://github.com/ChinaIceF/My-TODOs) - 简洁轻便的跨平台桌面待办小工具
37 |
38 |
39 | ## 许可证
40 | PyQt-SiliconUI 使用 [GPLv3](../LICENSE) 许可证
41 |
42 | 版权所有 © 2024 by ChinaIceF.
43 |
44 |
45 | ## 特别声明
46 | 用户阅读、下载、基于该软件开发或修改该软件,即代表用户已经理解并同意开源许可证声明的权利与限制,用户理解并同意不进行违反当地法律法规的开发或/和修改,若因用户的开发或/和修改违反了当地的法律,或是用户的开发或/和修改的传播和使用过程中违反了传播者和使用者所在地区适用的法律,或是造成了任何负面的个人或公众影响,用户应承担全部责任,本软件的开发者不承担任何责任。
47 |
48 |
--------------------------------------------------------------------------------
/docs/coding_standard.md:
--------------------------------------------------------------------------------
1 | # 代码规范
2 | 创建于 2024.10.25
3 |
4 | 为了提高可读性和可维护性,新编写的 PyQt-SiliconUI 代码将遵守以下规范。
5 |
6 | ## 命名规范
7 | ### 命名法
8 | * 变量名采用 snake_case。
9 | * 方法名沿袭 PyQt 特点,采用 lowerCamelCase
10 | * 类名采用 UpperCamelCase
11 | * 旗标类、枚举类和常量采用全大写命名
12 |
13 | ### 命名构成
14 | #### 变量名
15 | * 采用正常英文语序命名,例如 `day_counter`, `month_counter`, `year_counter`
16 | * 具有大量语义类似,而类型不同的变量,将强调的类型提前作为前缀,例如 `container_name`, `label_name`
17 | * 变量名与方法名冲突时,变量名后加 `_` 后缀,如 `self.name()`, `self.name_`
18 |
19 |
20 | ## 控件 / 组件类
21 | 约定模版化的方法和其功能。
22 |
23 | ### _initWidget()
24 | 初始化组件中需要用到的控件,仅做声明,不包含样式表,几何信息等。
25 |
26 | ### _initStyle()
27 | 初始化样式表、字体、颜色等外观相关的属性到自身以及 `_initWidget()` 声明的控件中。
28 |
29 | ### _initLayout()
30 | 初始化布局。除了使用 `QLayout` 外,几何信息也在这里定义,包括位置和大小。
31 |
32 | ### _initAnimation()
33 | 初始化动画。包括 `QPropertyAnimation` 和 `SiAnimation`,在这里完成他们的初始化和信号绑定。
34 | 例如:
35 | ```python
36 | def _initAnimation(self):
37 | self.animation = SiExpAnimation(self)
38 | self.animation.setFactor(1/8)
39 | self.animation.setBias(0.2)
40 | self.animation.setTarget(self.idle_color)
41 | self.animation.setCurrent(self.idle_color)
42 | self.animation.ticked.connect(self.animate)
43 | ```
44 |
45 | ### \_\_init\_\_()
46 | * 初始化变量。
47 | * 依次调用 `_initWidget()` `_initStyle()` `_initLayout()` `_initAnimation()`。
--------------------------------------------------------------------------------
/docs/template/layer.md:
--------------------------------------------------------------------------------
1 | # SiLayer
2 | 在应用界面上的可叠加容器,实现主界面、子界面、弹窗和侧边栏等等叠加场景。
3 |
4 | | | |
5 | |------:|:---------|
6 | | 继承自 | SiWidget |
7 | | 被继承对象 | - |
8 |
9 | ## 公共方法
10 | | 方法名 | 返回值类型 |
11 | |:-----------------------------------------|:---------|
12 | | setBody(SiWidget) | None |
13 | | body() | SiWidget |
14 | | setCloseUpperLayerOnDimClicked(on :bool) | None |
15 | | closeLayer() | None |
16 |
17 | ## 信号
18 | | 信号名 | 返回值类型 |
19 | |:--------------|:------|
20 | | closed | None |
21 | | closedToUpper | bool |
22 |
--------------------------------------------------------------------------------
/examples/Gallery for siui/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/__init__.py
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/components/__init__.py
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/option_card/__init__.py:
--------------------------------------------------------------------------------
1 | from .plane import *
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/option_card/plane.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from PyQt5.QtCore import Qt
4 |
5 | from siui.components import SiOptionCardPlane
6 | from siui.components.widgets import SiLabel, SiSimpleButton
7 | from siui.core import SiGlobal
8 | from siui.core import Si
9 |
10 |
11 | class OptionCardPlaneForWidgetDemos(SiOptionCardPlane):
12 | def __init__(self, *args, **kwargs):
13 | super().__init__(*args, **kwargs)
14 |
15 | self.source_code_url = None
16 |
17 | self.additional_description = SiLabel(self)
18 | self.additional_description.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged)
19 | self.additional_description.setFixedHeight(24)
20 | self.additional_description.setAlignment(Qt.AlignLeft | Qt.AlignBottom)
21 |
22 | self.button_bug = SiSimpleButton(self)
23 | self.button_bug.attachment().load(SiGlobal.siui.iconpack.get("ic_fluent_bug_regular"))
24 | self.button_bug.resize(32, 32)
25 | self.button_bug.setHint("报告问题")
26 | self.button_bug.clicked.connect(
27 | lambda: os.system("start https://github.com/ChinaIceF/PyQt-SiliconUI/issues/new"))
28 |
29 | self.button_source_code = SiSimpleButton(self)
30 | self.button_source_code.attachment().load(SiGlobal.siui.iconpack.get("ic_fluent_open_regular"))
31 | self.button_source_code.resize(32, 32)
32 | self.button_source_code.setHint("查看源代码")
33 | self.button_source_code.clicked.connect(self.openSourceCode)
34 |
35 | self.header().addWidget(self.additional_description, "left")
36 | self.header().addWidget(self.button_source_code, "right")
37 | self.header().addWidget(self.button_bug, "right")
38 |
39 | self.body().setSpacing(16)
40 |
41 | def setSourceCodeURL(self, url):
42 | self.source_code_url = url
43 |
44 | def openSourceCode(self):
45 | if self.source_code_url is None:
46 | raise ValueError("未指定源代码 URL")
47 | os.system(f"start {self.source_code_url}")
48 |
49 | def setAdditionalDescription(self, text: str):
50 | self.additional_description.setText(text)
51 |
52 | def reloadStyleSheet(self):
53 | super().reloadStyleSheet()
54 | self.additional_description.setStyleSheet("color: {}".format(SiGlobal.siui.colors["TEXT_C"]))
55 |
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_about/__init__.py:
--------------------------------------------------------------------------------
1 | from .page_about import About
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_about/page_about.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt, QUrl
2 | from PyQt5.QtGui import QDesktopServices
3 | from PyQt5.QtWidgets import QSizePolicy
4 |
5 | from siui.components import (
6 | SiDenseVContainer,
7 | SiLabel,
8 | SiOptionCardLinear,
9 | SiPixLabel,
10 | SiPushButton,
11 | SiSimpleButton,
12 | SiTitledWidgetGroup,
13 | )
14 | from siui.components.page import SiPage
15 | from siui.core import GlobalFont, Si, SiColor, SiGlobal, SiQuickEffect
16 | from siui.gui import SiFont
17 |
18 |
19 | class About(SiPage):
20 | def __init__(self, *args, **kwargs):
21 | super().__init__(*args, **kwargs)
22 |
23 | self.setPadding(64)
24 | self.setScrollMaximumWidth(950)
25 | self.setTitle("关于")
26 |
27 | self.titled_widget_group = SiTitledWidgetGroup(self)
28 | self.titled_widget_group.setSiliconWidgetFlag(Si.EnableAnimationSignals)
29 |
30 | version_picture_container = SiDenseVContainer(self)
31 | version_picture_container.setAlignment(Qt.AlignCenter)
32 | version_picture_container.setFixedHeight(128 + 48)
33 | SiQuickEffect.applyDropShadowOn(version_picture_container, color=(28, 25, 31, 255), blur_radius=48)
34 |
35 | self.version_picture = SiPixLabel(self)
36 | self.version_picture.setFixedSize(128, 128)
37 | self.version_picture.setBorderRadius(0)
38 | self.version_picture.load("./img/logo_new.png")
39 |
40 | self.version_label = SiLabel(self)
41 | self.version_label.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged)
42 | self.version_label.setFont(SiFont.tokenized(GlobalFont.M_NORMAL))
43 | self.version_label.setStyleSheet(f"color: {self.getColor(SiColor.TEXT_D)}")
44 | self.version_label.setText("PyQt-SiliconUI")
45 |
46 | version_picture_container.addWidget(self.version_picture)
47 | version_picture_container.addWidget(self.version_label)
48 | self.titled_widget_group.addWidget(version_picture_container)
49 |
50 | with self.titled_widget_group as group:
51 | group.addTitle("开源")
52 |
53 | self.button_to_repo = SiSimpleButton(self)
54 | self.button_to_repo.resize(32, 32)
55 | self.button_to_repo.attachment().load(SiGlobal.siui.iconpack.get("ic_fluent_open_regular"))
56 | self.button_to_repo.clicked.connect(lambda: QDesktopServices.openUrl(QUrl("https://github.com/ChinaIceF/PyQt-SiliconUI")))
57 |
58 | self.option_card_repo = SiOptionCardLinear(self)
59 | self.option_card_repo.setTitle("开源仓库", "在 GitHub 上查看 Silicon UI 的项目主页")
60 | self.option_card_repo.load(SiGlobal.siui.iconpack.get("ic_fluent_home_database_regular"))
61 | self.option_card_repo.addWidget(self.button_to_repo)
62 |
63 | self.option_card_license = SiOptionCardLinear(self)
64 | self.option_card_license.setTitle("开源许可证", "本项目遵循 GPLv3.0 许可证供非商业使用")
65 | self.option_card_license.load(SiGlobal.siui.iconpack.get("ic_fluent_certificate_regular"))
66 |
67 | group.addWidget(self.option_card_repo)
68 | group.addWidget(self.option_card_license)
69 |
70 | with self.titled_widget_group as group:
71 | group.addTitle("版权")
72 |
73 | self.option_card_copyright = SiOptionCardLinear(self)
74 | self.option_card_copyright.setTitle("版权声明", "PyQt-SiliconUI 版权所有 © 2024 by ChinaIceF")
75 | self.option_card_copyright.load(SiGlobal.siui.iconpack.get("ic_fluent_info_regular"))
76 |
77 | group.addWidget(self.option_card_copyright)
78 |
79 | with self.titled_widget_group as group:
80 | group.addTitle("第三方资源")
81 |
82 | self.option_card_icon_pack = SiOptionCardLinear(self)
83 | self.option_card_icon_pack.setTitle("Fluent UI 图标库", "本项目内置了 Fluent UI 图标库,Microsoft 公司保有这些图标的版权")
84 | self.option_card_icon_pack.load(SiGlobal.siui.iconpack.get("ic_fluent_diversity_regular"))
85 |
86 | group.addWidget(self.option_card_icon_pack)
87 |
88 | # add placeholder for better outfit
89 | self.titled_widget_group.addPlaceholder(64)
90 |
91 | # Set SiTitledWidgetGroup object as the attachment of the page's scroll area
92 | self.setAttachment(self.titled_widget_group)
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_container/__init__.py:
--------------------------------------------------------------------------------
1 | from .page_container import ExampleContainer
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_dialog/__init__.py:
--------------------------------------------------------------------------------
1 | from .page_dialog import ExampleDialogs
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_dialog/components/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/components/page_dialog/components/__init__.py
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_dialog/components/modal_dialog_example.py:
--------------------------------------------------------------------------------
1 | from siui.components import SiLabel, SiLongPressButton, SiPushButton
2 | from siui.core import SiColor, SiGlobal
3 | from siui.templates.application.components.dialog.modal import SiModalDialog
4 |
5 |
6 | class ModalDialogExample(SiModalDialog):
7 | def __init__(self, *args, **kwargs):
8 | super().__init__(*args, **kwargs)
9 |
10 | self.setFixedWidth(500)
11 | self.icon().load(SiGlobal.siui.iconpack.get("ic_fluent_save_filled",
12 | color_code=SiColor.mix(
13 | self.getColor(SiColor.SVG_NORMAL),
14 | self.getColor(SiColor.INTERFACE_BG_B),
15 | 0.05))
16 | )
17 |
18 | label = SiLabel(self)
19 | label.setStyleSheet(f"color: {self.getColor(SiColor.TEXT_E)}")
20 | label.setText(
21 | f'是否保存刚刚编辑的文件?
'
22 | "
"
23 | "- 田所浩二志.doc
"
24 | "- 八十天游览下北泽——从百草园到三味书屋.docx
"
25 | "- 小黑子是怎样练成的.pdf"
26 | )
27 | label.adjustSize()
28 | self.contentContainer().addWidget(label)
29 |
30 | button1 = SiPushButton(self)
31 | button1.setFixedHeight(32)
32 | button1.attachment().setText("继续编辑我的文档")
33 | button1.colorGroup().assign(SiColor.BUTTON_PANEL, self.getColor(SiColor.INTERFACE_BG_D))
34 | button1.clicked.connect(SiGlobal.siui.windows["MAIN_WINDOW"].layerModalDialog().closeLayer)
35 |
36 | button2 = SiPushButton(self)
37 | button2.setFixedHeight(32)
38 | button2.attachment().setText("保存并退出")
39 | button2.colorGroup().assign(SiColor.BUTTON_PANEL, self.getColor(SiColor.INTERFACE_BG_D))
40 | button2.clicked.connect(SiGlobal.siui.windows["MAIN_WINDOW"].layerModalDialog().closeLayer)
41 |
42 | self.button3 = SiLongPressButton(self)
43 | self.button3.setFixedHeight(32)
44 | self.button3.attachment().setText("丢弃一切创作成果并退出")
45 | self.button3.longPressed.connect(SiGlobal.siui.windows["MAIN_WINDOW"].layerModalDialog().closeLayer)
46 |
47 | self.buttonContainer().addWidget(button1)
48 | self.buttonContainer().addWidget(button2)
49 | self.buttonContainer().addWidget(self.button3)
50 |
51 | SiGlobal.siui.reloadStyleSheetRecursively(self)
52 | self.adjustSize()
53 |
54 | def deleteLater(self):
55 | # print("你好")
56 | self.button3.hold_thread.safe_to_stop = True
57 | self.button3.hold_thread.wait()
58 | self.button3.deleteLater()
59 | SiGlobal.siui.windows["TOOL_TIP"].setNowInsideOf(None)
60 | SiGlobal.siui.windows["TOOL_TIP"].hide_()
61 | super().deleteLater()
62 |
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_dialog/components/side_msg_box.py:
--------------------------------------------------------------------------------
1 | from siui.components import SiDenseHContainer, SiDenseVContainer, SiLabel, SiPixLabel, SiSimpleButton
2 | from siui.core import GlobalFont, SiColor, SiGlobal
3 | from siui.gui import SiFont
4 | from siui.templates.application.components.message.box import SiSideMessageBox
5 |
6 |
7 | def send_simple_message(type_, auto_close=False, auto_close_duration=1000):
8 | fold_after = auto_close_duration if auto_close is True else None
9 | SiGlobal.siui.windows["MAIN_WINDOW"].LayerRightMessageSidebar().send(
10 | "这是一条测试消息\n"
11 | "比具标题信息更加简洁方便",
12 | msg_type=type_,
13 | fold_after=fold_after,
14 | )
15 |
16 |
17 | def send_titled_message(type_, auto_close=False, auto_close_duration=1000):
18 | fold_after = auto_close_duration if auto_close is True else None
19 | SiGlobal.siui.windows["MAIN_WINDOW"].LayerRightMessageSidebar().send(
20 | title="Sent Successfully",
21 | text="A titled message has been successfully sent to the sidebar.\n" +
22 | "Click this message box for more information.",
23 | msg_type=type_,
24 | fold_after=fold_after,
25 | )
26 |
27 |
28 | def send_custom_message(type_, auto_close=False, auto_close_duration=1000):
29 | fold_after = auto_close_duration if auto_close is True else None
30 | container = SiDenseHContainer()
31 | container.setAdjustWidgetsSize(True)
32 | container.setFixedHeight(80)
33 | container.setSpacing(0)
34 |
35 | info_label = SiLabel()
36 | info_label.setFont(SiFont.tokenized(GlobalFont.S_NORMAL))
37 | info_label.setStyleSheet(f"color: {info_label.getColor(SiColor.TEXT_D)}; padding-left: 16px")
38 | info_label.setText("以下账号已成功登录")
39 | info_label.adjustSize()
40 |
41 | split_line = SiLabel()
42 | split_line.resize(300, 1)
43 | split_line.setFixedStyleSheet("margin-left: 20px")
44 | split_line.setColor(SiColor.trans(split_line.getColor(SiColor.TEXT_D), 0.3))
45 |
46 | avatar = SiPixLabel(container)
47 | avatar.resize(80, 80)
48 | avatar.setBorderRadius(40)
49 | avatar.load("./img/avatar1.png")
50 | avatar.setHint("霏泠Ice")
51 |
52 | container_v = SiDenseVContainer(container)
53 | container_v.setFixedWidth(200)
54 | container_v.setSpacing(0)
55 |
56 | name_label = SiLabel()
57 | name_label.setFont(SiFont.tokenized(GlobalFont.M_BOLD))
58 | name_label.setStyleSheet(f"color: {name_label.getColor(SiColor.TEXT_B)}; padding-left:8px")
59 | name_label.setText("霏泠Ice")
60 | name_label.adjustSize()
61 |
62 | button_1 = SiSimpleButton()
63 | button_1.setFixedHeight(22)
64 | button_1.attachment().setText("打开我的主页")
65 | button_1.colorGroup().assign(SiColor.TEXT_B, button_1.getColor(SiColor.TITLE_INDICATOR))
66 | button_1.adjustSize()
67 | button_1.reloadStyleSheet()
68 |
69 | button_2 = SiSimpleButton()
70 | button_2.setFixedHeight(22)
71 | button_2.attachment().setText("退出账号")
72 | button_2.colorGroup().assign(SiColor.TEXT_B, button_2.getColor(SiColor.TITLE_INDICATOR))
73 | button_2.adjustSize()
74 | button_2.reloadStyleSheet()
75 |
76 | container_v.addWidget(name_label)
77 | container_v.addPlaceholder(8)
78 | container_v.addWidget(button_1)
79 | container_v.addWidget(button_2)
80 | container_v.adjustSize()
81 |
82 | container.addPlaceholder(24)
83 | container.addWidget(avatar)
84 | container.addPlaceholder(8)
85 | container.addWidget(container_v)
86 | container.adjustSize()
87 |
88 | new_message_box = SiSideMessageBox()
89 | new_message_box.setMessageType(type_)
90 | new_message_box.content().container().setSpacing(0)
91 | new_message_box.content().container().addPlaceholder(16)
92 | new_message_box.content().container().addWidget(info_label)
93 | new_message_box.content().container().addPlaceholder(8)
94 | new_message_box.content().container().addWidget(split_line)
95 | new_message_box.content().container().addPlaceholder(24)
96 | new_message_box.content().container().addWidget(container)
97 | new_message_box.content().container().addPlaceholder(32)
98 | new_message_box.adjustSize()
99 |
100 | if fold_after is not None:
101 | new_message_box.setFoldAfter(fold_after)
102 |
103 | SiGlobal.siui.windows["MAIN_WINDOW"].LayerRightMessageSidebar().sendMessageBox(new_message_box)
104 |
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_functional/__init__.py:
--------------------------------------------------------------------------------
1 | from .page_functional import ExampleFunctional
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_functional/components/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/components/page_functional/components/__init__.py
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_functional/components/music_displayer/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/components/page_functional/components/music_displayer/__init__.py
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_functional/page_functional.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt
2 |
3 | from siui.components import SiTitledWidgetGroup, SiPushButton, SiLabel, SiLongPressButton, SiDenseHContainer, \
4 | SiMasonryContainer
5 | from siui.components.combobox import SiComboBox
6 | from siui.components.page import SiPage
7 | from siui.core import SiColor
8 | from siui.core import SiQuickEffect
9 | from siui.core import SiGlobal
10 | from siui.templates.application.components.dialog.modal import SiModalDialog
11 |
12 | from ..option_card import OptionCardPlaneForWidgetDemos
13 | from .components.music_displayer.music_displayer import SiMusicDisplayer
14 |
15 | class ExampleFunctional(SiPage):
16 | def __init__(self, *args, **kwargs):
17 | super().__init__(*args, **kwargs)
18 |
19 | self.setPadding(64)
20 | self.setScrollMaximumWidth(1040)
21 | self.setScrollAlignment(Qt.AlignHCenter)
22 | self.setTitle("功能组件")
23 |
24 | # 创建控件组
25 | self.titled_widgets_group = SiTitledWidgetGroup(self)
26 | self.titled_widgets_group.setSpacing(32)
27 | self.titled_widgets_group.setAdjustWidgetsSize(False) # 禁用调整宽度
28 |
29 | # 音乐展示框
30 | with self.titled_widgets_group as group:
31 | group.addTitle("音乐展示框")
32 |
33 | self.displayer_container = SiMasonryContainer(self)
34 | self.displayer_container.setColumns(2)
35 | self.displayer_container.setColumnWidth(512)
36 | self.displayer_container.setFixedWidth(512 + 512 + 16)
37 | self.displayer_container.setSpacing(horizontal=16, vertical=16)
38 |
39 | self.demo_displayer_1 = SiMusicDisplayer(self)
40 | self.demo_displayer_1.resize(512, 128)
41 | self.demo_displayer_1.loadInfo("./img/pages/functional/music_covers/cover1.jpg", "Moon Without The Stars", "Unknown Artist", "Unknown Album") # noqa: E501
42 |
43 | self.demo_displayer_2 = SiMusicDisplayer(self)
44 | self.demo_displayer_2.resize(512, 128)
45 | self.demo_displayer_2.loadInfo("./img/pages/functional/music_covers/cover2.png", "Never Gonna Give You Up", "Rick Astley", "Whenever You Need Somebody") # noqa: E501
46 |
47 | self.demo_displayer_3 = SiMusicDisplayer(self)
48 | self.demo_displayer_3.resize(512, 128)
49 | self.demo_displayer_3.loadInfo("./img/pages/functional/music_covers/cover3.png", "Friend", "玉置浩二", "ワインレッドの心") # noqa: E501
50 |
51 | self.demo_displayer_4 = SiMusicDisplayer(self)
52 | self.demo_displayer_4.resize(512, 128)
53 | self.demo_displayer_4.loadInfo("./img/pages/functional/music_covers/cover4.png", "雨中的重逢", "Parion圆周率", "Reunion In The Rain") # noqa: E501
54 |
55 | self.demo_displayer_5 = SiMusicDisplayer(self)
56 | self.demo_displayer_5.resize(512, 128)
57 | self.demo_displayer_5.loadInfo("./img/pages/functional/music_covers/cover5.png", "Melting White", "塞壬唱片-MSR / Cubes Collective", "Melting White") # noqa: E501
58 |
59 | self.demo_displayer_6 = SiMusicDisplayer(self)
60 | self.demo_displayer_6.resize(512, 128)
61 | self.demo_displayer_6.loadInfo("./img/pages/functional/music_covers/cover6.png", "Axolotl", "C418", "Axolotl") # noqa: E501
62 |
63 | self.displayer_container.addWidget(self.demo_displayer_1)
64 | self.displayer_container.addWidget(self.demo_displayer_2)
65 | self.displayer_container.addWidget(self.demo_displayer_3)
66 | self.displayer_container.addWidget(self.demo_displayer_4)
67 | self.displayer_container.addWidget(self.demo_displayer_5)
68 | self.displayer_container.addWidget(self.demo_displayer_6)
69 |
70 | group.addWidget(self.displayer_container)
71 |
72 | # 添加页脚的空白以增加美观性
73 | self.titled_widgets_group.addPlaceholder(64)
74 |
75 | # 设置控件组为页面对象
76 | self.setAttachment(self.titled_widgets_group)
77 |
78 |
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_homepage/__init__.py:
--------------------------------------------------------------------------------
1 | from .page_homepage import ExampleHomepage
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_homepage/components/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/components/page_homepage/components/__init__.py
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_homepage/components/themed_option_card.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from PyQt5.QtCore import Qt
4 |
5 | from siui.components.option_card import SiOptionCardPlane
6 | from siui.components.widgets import SiDenseVContainer, SiLabel, SiSimpleButton
7 | from siui.core import SiGlobal
8 | from siui.core import Si
9 |
10 |
11 | class ThemedOptionCardPlane(SiOptionCardPlane):
12 | def __init__(self, *args, **kwargs):
13 | super().__init__(*args, **kwargs)
14 |
15 | self.my_theme_color = "#855198"
16 | self.setSpacing(32)
17 |
18 | # 标题边的指示器
19 | self.title_indicator = SiLabel(self)
20 | self.title_indicator.setGeometry(0, 24, 4, 18)
21 |
22 | # 解释说明
23 | self.description = SiLabel(self)
24 | self.description.setWordWrap(True)
25 | self.description.setFixedHeight(128)
26 | self.description.setAlignment(Qt.AlignLeft | Qt.AlignTop)
27 | self.body().setAdjustWidgetsSize(True)
28 | self.body().addWidget(self.description)
29 |
30 | # 链接按钮
31 | self.link_button = SiSimpleButton(self)
32 | self.link_button.setFixedSize(32, 32)
33 | self.link_button.attachment().load(SiGlobal.siui.iconpack.get("ic_fluent_open_regular"))
34 |
35 | link_button_container = SiDenseVContainer(self)
36 | link_button_container.setAlignment(Qt.AlignCenter)
37 | link_button_container.setFixedHeight(48)
38 | link_button_container.addWidget(self.link_button)
39 | self.footer().setSiliconWidgetFlag(Si.EnableAnimationSignals)
40 | self.footer().resized.connect(lambda size: link_button_container.setFixedWidth(size[0]))
41 | self.footer().setFixedHeight(48)
42 | self.footer().addWidget(link_button_container)
43 |
44 | def setDescription(self, text):
45 | self.description.setText(f"{text}
")
46 |
47 | def setThemeColor(self, color_code):
48 | self.my_theme_color = color_code
49 | self.reloadStyleSheet()
50 |
51 | def setURL(self, url):
52 | self.link_button.setHint(url)
53 | self.link_button.clicked.connect(lambda: os.system(f"start {url}"))
54 |
55 | def reloadStyleSheet(self):
56 | super().reloadStyleSheet()
57 |
58 | self.outfit_label_upper.setStyleSheet(
59 | """
60 | border-radius: 8px; background-color: {}
61 | """.format(SiGlobal.siui.colors["INTERFACE_BG_C"])
62 | )
63 | self.outfit_label_lower.setStyleSheet(f"border-radius: 8px; background-color: {self.my_theme_color}")
64 | self.title_indicator.setStyleSheet(f"border-radius: 2px; background-color: {self.my_theme_color}")
65 | self.description.setStyleSheet("color: {}".format(SiGlobal.siui.colors["TEXT_B"]))
66 |
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_icons/__init__.py:
--------------------------------------------------------------------------------
1 | from .page_icons import ExampleIcons
2 |
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_option_cards/__init__.py:
--------------------------------------------------------------------------------
1 | from .page_option_cards import ExampleOptionCards
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_page_control/__init__.py:
--------------------------------------------------------------------------------
1 | from .page_control import ExamplePageControl
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_page_control/page_control.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt
2 |
3 | from siui.components import (
4 | SiPushButton,
5 | SiTitledWidgetGroup,
6 | )
7 | from siui.components.page import SiPage
8 | from siui.core import SiGlobal
9 |
10 | from ..option_card import OptionCardPlaneForWidgetDemos
11 |
12 |
13 | class ExamplePageControl(SiPage):
14 | def __init__(self, *args, **kwargs):
15 | super().__init__(*args, **kwargs)
16 |
17 | self.setPadding(64)
18 | self.setScrollMaximumWidth(950)
19 | self.setScrollAlignment(Qt.AlignLeft)
20 | self.setTitle("页面控制")
21 |
22 | # 创建控件组
23 | self.titled_widgets_group = SiTitledWidgetGroup(self)
24 | self.titled_widgets_group.setSpacing(32)
25 | self.titled_widgets_group.setAdjustWidgetsSize(False) # 禁用调整宽度
26 |
27 | # 侧边栏信息
28 | with self.titled_widgets_group as group:
29 | group.addTitle("页面偏移")
30 |
31 | # 侧边栏信息
32 | self.global_shifting = OptionCardPlaneForWidgetDemos(self)
33 | self.global_shifting.setSourceCodeURL("https://github.com/ChinaIceF/PyQt-SiliconUI/blob/main/siui/components"
34 | "/widgets/progress_bar/progress_bar.py")
35 | self.global_shifting.setTitle("页面偏移")
36 | self.global_shifting.setFixedWidth(800)
37 |
38 | self.ctrl_shift_left = SiPushButton(self)
39 | self.ctrl_shift_left.resize(128, 32)
40 | self.ctrl_shift_left.attachment().setText("向左偏移")
41 | self.ctrl_shift_left.clicked.connect(
42 | lambda: SiGlobal.siui.windows["MAIN_WINDOW"].groups()["MAIN_INTERFACE"].moveTo(-100, 0))
43 |
44 | self.ctrl_shift_right = SiPushButton(self)
45 | self.ctrl_shift_right.resize(128, 32)
46 | self.ctrl_shift_right.attachment().setText("向右偏移")
47 | self.ctrl_shift_right.clicked.connect(
48 | lambda: SiGlobal.siui.windows["MAIN_WINDOW"].groups()["MAIN_INTERFACE"].moveTo(100, 0))
49 |
50 | self.ctrl_shift_restore = SiPushButton(self)
51 | self.ctrl_shift_restore.resize(128, 32)
52 | self.ctrl_shift_restore.attachment().setText("恢复")
53 | self.ctrl_shift_restore.clicked.connect(
54 | lambda: SiGlobal.siui.windows["MAIN_WINDOW"].groups()["MAIN_INTERFACE"].moveTo(0, 0))
55 |
56 | self.global_shifting.body().addWidget(self.ctrl_shift_left)
57 | self.global_shifting.body().addWidget(self.ctrl_shift_right)
58 | self.global_shifting.body().addWidget(self.ctrl_shift_restore)
59 | self.global_shifting.body().addPlaceholder(12)
60 | self.global_shifting.adjustSize()
61 |
62 | group.addWidget(self.global_shifting)
63 |
64 | # 添加页脚的空白以增加美观性
65 | self.titled_widgets_group.addPlaceholder(64)
66 |
67 | # 设置控件组为页面对象
68 | self.setAttachment(self.titled_widgets_group)
69 |
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_refactor/__init__.py:
--------------------------------------------------------------------------------
1 | from .page_refactor import RefactoredWidgets
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_widgets/__init__.py:
--------------------------------------------------------------------------------
1 | from .page_widgets import ExampleWidgets
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_widgets/components/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/components/page_widgets/components/__init__.py
--------------------------------------------------------------------------------
/examples/Gallery for siui/components/page_widgets/components/demo_tables.py:
--------------------------------------------------------------------------------
1 | from siui.components import SiLabel, SiPixLabel
2 | from siui.components.widgets.abstracts.table import ABCSiTabelManager, SiRow
3 | from siui.core import GlobalFont, Si, SiColor
4 | from siui.gui import SiFont
5 |
6 |
7 | class DemoOsuPlayerRankingTableManager(ABCSiTabelManager):
8 | # #0 排名 SiLabel
9 | # #1 评级图片 SiPixLabel
10 | # #2 得分 SiLabel
11 | # #3 准确度 SiLabel
12 | # #4 国旗 SiPixLabel
13 | # #5 玩家用户名 SiLabel
14 | # #6 GREAT SiLabel
15 | # #7 OK SiLabel
16 | # #8 MEM SiLabel
17 | # #9 MISS SiLabel
18 | # #10 PP SiLabel
19 |
20 | rank_dict = {
21 | "S": "./img/table/ranks/rank_s.png",
22 | "SS": "./img/table/ranks/rank_ss.png",
23 | }
24 |
25 | country_dict = {
26 | "China": "./img/table/flags/CN.png",
27 | "United State": "./img/table/flags/UM.png",
28 | "Great Britain": "./img/table/flags/GB.png",
29 | }
30 |
31 | def _value_read_parser(self, row_index, col_index):
32 | if col_index in [0, 2, 3, 5, 6, 7, 8, 9, 10]:
33 | return self.parent().getRowWidget(row_index)[col_index].text()
34 |
35 | if col_index in [1, 4]:
36 | path = self.parent().getRowWidget(row_index)[col_index].path()
37 | return list(self.country_dict.keys())[list(self.country_dict.values()).index(path)]
38 |
39 | def _value_write_parser(self, row_index, col_index, value):
40 | widget = self.parent().getRowWidget(row_index)[col_index]
41 | if col_index == 0:
42 | widget.setFont(SiFont.tokenized(GlobalFont.S_BOLD))
43 | widget.setTextColor(self.parent().getColor(SiColor.TEXT_B))
44 |
45 | if col_index == 1:
46 | widget.load(self.rank_dict[value])
47 | widget.setHint(value)
48 |
49 | if col_index == 2:
50 | widget.setTextColor(self.parent().getColor(SiColor.TEXT_B))
51 | if row_index == 0:
52 | widget.setFont(SiFont.tokenized(GlobalFont.S_BOLD))
53 | else:
54 | widget.setFont(SiFont.tokenized(GlobalFont.S_NORMAL))
55 |
56 | if col_index == 3:
57 | if value == "100.00%":
58 | widget.setTextColor("#B2D844")
59 | else:
60 | widget.setTextColor(self.parent().getColor(SiColor.TEXT_B))
61 |
62 | if col_index == 4:
63 | widget.load(self.country_dict[value])
64 | widget.setHint(value)
65 |
66 | if col_index == 5:
67 | widget.setTextColor(self.parent().getColor(SiColor.TEXT_THEME))
68 | widget.setHint("Click to view profile")
69 |
70 | if col_index in [6, 7, 8, 9, 10]:
71 | if value == "0":
72 | widget.setTextColor(self.parent().getColor(SiColor.TEXT_E))
73 | else:
74 | widget.setTextColor(self.parent().getColor(SiColor.TEXT_B))
75 |
76 | if col_index in [0, 2, 3, 5, 6, 7, 8, 9, 10]:
77 | widget.setText(value)
78 |
79 | def _widget_creator(self, col_index):
80 | if col_index in [0, 2, 3, 5, 6, 7, 8, 9, 10]:
81 | label = SiLabel(self.parent())
82 | label.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged)
83 | return label
84 | if col_index == 1:
85 | pix_label = SiPixLabel(self.parent())
86 | pix_label.resize(48, 24)
87 | pix_label.setBorderRadius(0)
88 | return pix_label
89 | if col_index == 4:
90 | pix_label = SiPixLabel(self.parent())
91 | pix_label.resize(33, 24)
92 | pix_label.setBorderRadius(0)
93 | return pix_label
94 |
95 | def on_header_created(self, header: SiRow):
96 | for name in self.parent().column_names:
97 | new_label = SiLabel(self.parent())
98 | new_label.setFont(SiFont.tokenized(GlobalFont.S_BOLD))
99 | new_label.setTextColor(self.parent().getColor(SiColor.TEXT_D))
100 | new_label.setText(name)
101 | new_label.adjustSize()
102 | header.container().addWidget(new_label)
103 |
104 | header.container().arrangeWidgets()
105 |
106 |
--------------------------------------------------------------------------------
/examples/Gallery for siui/icons/__init__.py:
--------------------------------------------------------------------------------
1 | from .parser import *
2 |
--------------------------------------------------------------------------------
/examples/Gallery for siui/icons/icons.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/icons/icons.dat
--------------------------------------------------------------------------------
/examples/Gallery for siui/icons/parser.py:
--------------------------------------------------------------------------------
1 | import numpy
2 | import os
3 |
4 | current_module_path = os.path.dirname(os.path.abspath(__file__))
5 | data_file_path = os.path.join(current_module_path, './icons.dat')
6 |
7 | class IconDictionary:
8 | def __init__(self, library_path=data_file_path, color=None):
9 |
10 | # !注意! 你不应使用这些文件,他们已经过加密处理
11 | # 如果你需要这些图标文件,你可以直接在 flaticon.com 免费获取他们
12 |
13 | # 读取数据并解密
14 | f = open(library_path, 'rb')
15 | library_raw = f.read()
16 | library_list = list(library_raw)
17 | library = bytes(list((numpy.array(library_list) + numpy.array(range(len(library_list))) * 17) % 255)).decode() # 解密
18 |
19 | # 整理成字典
20 | items = library.split('!!!')
21 | names = []
22 | datas = []
23 | for item in items[1:]:
24 | name, data = item.split('###')
25 | data = data.replace('/>', ' fill="{}" />'.format(color))
26 | names.append(name)
27 | datas.append(data.encode())
28 | self.icons = dict(zip(names, datas))
29 |
30 | def get(self, name):
31 | svg_data = self.icons[name]
32 | return svg_data.encode()
33 |
--------------------------------------------------------------------------------
/examples/Gallery for siui/img/about_version.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/img/about_version.png
--------------------------------------------------------------------------------
/examples/Gallery for siui/img/avatar1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/img/avatar1.png
--------------------------------------------------------------------------------
/examples/Gallery for siui/img/avatar2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/img/avatar2.png
--------------------------------------------------------------------------------
/examples/Gallery for siui/img/empty_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/img/empty_icon.png
--------------------------------------------------------------------------------
/examples/Gallery for siui/img/homepage_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/img/homepage_background.png
--------------------------------------------------------------------------------
/examples/Gallery for siui/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/img/logo.png
--------------------------------------------------------------------------------
/examples/Gallery for siui/img/logo_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/img/logo_new.png
--------------------------------------------------------------------------------
/examples/Gallery for siui/img/pages/functional/music_covers/cover1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/img/pages/functional/music_covers/cover1.jpg
--------------------------------------------------------------------------------
/examples/Gallery for siui/img/pages/functional/music_covers/cover2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/img/pages/functional/music_covers/cover2.png
--------------------------------------------------------------------------------
/examples/Gallery for siui/img/pages/functional/music_covers/cover3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/img/pages/functional/music_covers/cover3.png
--------------------------------------------------------------------------------
/examples/Gallery for siui/img/pages/functional/music_covers/cover4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/img/pages/functional/music_covers/cover4.png
--------------------------------------------------------------------------------
/examples/Gallery for siui/img/pages/functional/music_covers/cover5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/img/pages/functional/music_covers/cover5.png
--------------------------------------------------------------------------------
/examples/Gallery for siui/img/pages/functional/music_covers/cover6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/img/pages/functional/music_covers/cover6.png
--------------------------------------------------------------------------------
/examples/Gallery for siui/img/table/flags/CN.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/img/table/flags/CN.png
--------------------------------------------------------------------------------
/examples/Gallery for siui/img/table/flags/GB.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/img/table/flags/GB.png
--------------------------------------------------------------------------------
/examples/Gallery for siui/img/table/flags/UM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/img/table/flags/UM.png
--------------------------------------------------------------------------------
/examples/Gallery for siui/img/table/ranks/rank_s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/img/table/ranks/rank_s.png
--------------------------------------------------------------------------------
/examples/Gallery for siui/img/table/ranks/rank_ss.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/Gallery for siui/img/table/ranks/rank_ss.png
--------------------------------------------------------------------------------
/examples/Gallery for siui/start.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import time
3 |
4 | from PyQt5.QtCore import QTimer
5 | from PyQt5.QtWidgets import QApplication
6 | from ui import MySiliconApp
7 |
8 | import siui
9 | from siui.core import SiGlobal
10 |
11 | #
12 | # siui.gui.set_scale_factor(1)
13 |
14 |
15 | def show_version_message(window):
16 | window.LayerRightMessageSidebar().send(
17 | title="Welcome to Silicon UI Gallery",
18 | text="You are currently running v1.14.514\n"
19 | "Click this message box to check out what's new.",
20 | msg_type=1,
21 | icon=SiGlobal.siui.iconpack.get("ic_fluent_hand_wave_filled"),
22 | fold_after=5000,
23 | slot=lambda: window.LayerRightMessageSidebar().send("Oops, it seems that nothing will happen due to the fact "
24 | "that this function is currently not completed.",
25 | icon=SiGlobal.siui.iconpack.get("ic_fluent_info_regular"))
26 | )
27 |
28 | window.LayerRightMessageSidebar().send(
29 | title="Refactoring in Progress",
30 | text="To optimize the project structure, "
31 | "we are currently undergoing a refactoring process.\n\n"
32 | "We strongly discourage you from using any deprecated components "
33 | 'other than those displayed on the "Refactored Components" page.',
34 | msg_type=4,
35 | icon=SiGlobal.siui.iconpack.get("ic_fluent_warning_filled"),
36 | )
37 |
38 |
39 | if __name__ == "__main__":
40 | app = QApplication(sys.argv)
41 |
42 | window = MySiliconApp()
43 | window.show()
44 |
45 | timer = QTimer(window)
46 | timer.singleShot(500, lambda: show_version_message(window))
47 |
48 | sys.exit(app.exec_())
49 |
--------------------------------------------------------------------------------
/examples/Gallery for siui/test_new_button.py:
--------------------------------------------------------------------------------
1 | # NOTE This is the refactor of button component. It's working in progress. It will
2 | # replace button once it's done. Now it's draft, code may be ugly and verbose temporarily.
3 | from __future__ import annotations
4 |
5 | import os
6 |
7 | from PyQt5.QtCore import QRect, QRectF, Qt
8 | from PyQt5.QtGui import QColor, QIcon, QPainter, QPainterPath, QPaintEvent
9 | from PyQt5.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget
10 |
11 | from siui.core import GlobalFont, SiColor, SiExpAnimation
12 | from siui.gui import SiFont
13 |
14 | os.environ["QT_SCALE_FACTOR"] = str(2)
15 |
16 |
17 | class SiPushButton(QPushButton):
18 | def __init__(self, parent: QWidget | None = None) -> None:
19 | super().__init__(parent)
20 |
21 | self.idle_color = SiColor.toArray("#00FFFFFF")
22 | self.hover_color = SiColor.toArray("#10FFFFFF")
23 | self.click_color = SiColor.toArray("#40FFFFFF")
24 |
25 | self.animation = SiExpAnimation(self)
26 | self.animation.setFactor(1/8)
27 | self.animation.setBias(0.2)
28 | self.animation.setTarget(self.idle_color)
29 | self.animation.setCurrent(self.idle_color)
30 | self.animation.ticked.connect(self.animate)
31 |
32 | self.clicked.connect(self._onButtonClicked)
33 |
34 | @classmethod
35 | def withText(cls, text: str, parent: QWidget | None = None) -> "SiPushButton":
36 | cls = cls(parent)
37 | cls.setText(text)
38 | return cls
39 |
40 | @classmethod
41 | def withIcon(cls, icon: QIcon, parent: QWidget | None = None) -> "SiPushButton":
42 | cls = cls(parent)
43 | cls.setIcon(icon)
44 | return cls
45 |
46 | def withTextAndIcon(cls, text: str, icon: str, parent: QWidget | None = None) -> "SiPushButton":
47 | cls = cls(parent)
48 | cls.setText(text)
49 | cls.setIcon(icon)
50 | return cls
51 |
52 | @property
53 | def bottomBorderHeight(self) -> int:
54 | return round(3)
55 |
56 | @staticmethod
57 | def _drawBackgroundPath(rect: QRect) -> QPainterPath:
58 | path = QPainterPath()
59 | path.addRoundedRect(QRectF(0, 0, rect.width(), rect.height()), 4, 4)
60 | return path
61 |
62 | def _drawBackgroundRect(self, painter: QPainter, rect: QRect) -> None:
63 | painter.setBrush(QColor("#2D2932"))
64 | painter.drawPath(self._drawBackgroundPath(rect))
65 |
66 | def _drawButtonPath(self, rect: QRect) -> QPainterPath:
67 | path = QPainterPath()
68 | path.addRoundedRect(QRectF(0, 0, rect.width(), rect.height() - self.bottomBorderHeight), 3, 3)
69 | return path
70 |
71 | def _drawButtonRect(self, painter: QPainter, rect: QRect) -> None:
72 | painter.setBrush(QColor("#4C4554"))
73 | painter.drawPath(self._drawButtonPath(rect))
74 |
75 | def _drawHighLightRect(self, painter: QPainter, rect: QRect) -> None:
76 | painter.setBrush(QColor(SiColor.toCode(self.animation.current_)))
77 | painter.drawPath(self._drawButtonPath(rect))
78 |
79 | def _onButtonClicked(self) -> None:
80 | self.animation.setCurrent(self.click_color)
81 | self.animation.start()
82 |
83 | def animate(self, _) -> None:
84 | self.update()
85 |
86 | def enterEvent(self, event) -> None:
87 | super().enterEvent(event)
88 | self.animation.setTarget(self.hover_color)
89 | self.animation.start()
90 |
91 | def leaveEvent(self, event) -> None:
92 | super().leaveEvent(event)
93 | self.animation.setTarget(self.idle_color)
94 | self.animation.start()
95 |
96 | def resizeEvent(self, event) -> None:
97 | super().resizeEvent(event)
98 |
99 | def paintEvent(self, event: QPaintEvent) -> None:
100 | painter = QPainter(self)
101 | painter.setRenderHint(QPainter.RenderHint.Antialiasing)
102 | painter.setRenderHint(QPainter.TextAntialiasing)
103 |
104 | painter.setPen(Qt.PenStyle.NoPen)
105 | rect = self.rect()
106 | self._drawBackgroundRect(painter, rect)
107 | self._drawButtonRect(painter, rect)
108 | self._drawHighLightRect(painter, rect)
109 |
110 | text_rect = QRect(0, 0, self.width(), self.height() - 4)
111 | painter.setPen(QColor(239, 239, 239)) # 设置文本颜色
112 | painter.setFont(self.font()) # 设置字体和大小
113 | painter.drawText(text_rect, Qt.AlignCenter, self.text()) # 在按钮中心绘制文本
114 | painter.end()
115 |
116 |
117 | class Window(QWidget):
118 | def __init__(self) -> None:
119 | super().__init__()
120 | self.resize(600, 800)
121 | self.setStyleSheet("background-color: #332E38")
122 |
123 | self.btn = SiPushButton(self)
124 | self.btn.setFixedSize(128, 32)
125 | self.btn.setFont(SiFont.tokenized(GlobalFont.S_NORMAL))
126 | self.btn.setText("我是按钮")
127 | self.btn.clicked.connect(lambda: print("clicked!"))
128 |
129 | self.main_layout = QVBoxLayout(self)
130 | self.main_layout.addWidget(self.btn, alignment=Qt.AlignmentFlag.AlignCenter)
131 |
132 |
133 | if __name__ == "__main__":
134 | app = QApplication([])
135 | window = Window()
136 | window.show()
137 | app.exec()
--------------------------------------------------------------------------------
/examples/Gallery for siui/ui.py:
--------------------------------------------------------------------------------
1 | import icons
2 | from components.page_about import About
3 | from components.page_container import ExampleContainer
4 | from components.page_dialog import ExampleDialogs
5 | from components.page_functional import ExampleFunctional
6 | from components.page_homepage import ExampleHomepage
7 | from components.page_icons import ExampleIcons
8 | from components.page_option_cards import ExampleOptionCards
9 | from components.page_page_control import ExamplePageControl
10 | from components.page_refactor import RefactoredWidgets
11 | from components.page_widgets import ExampleWidgets
12 | from PyQt5.QtGui import QIcon
13 | from PyQt5.QtWidgets import QDesktopWidget
14 |
15 | import siui
16 | from siui.core import SiColor, SiGlobal
17 | from siui.templates.application.application import SiliconApplication
18 |
19 | # 载入图标
20 | siui.core.globals.SiGlobal.siui.loadIcons(
21 | icons.IconDictionary(color=SiGlobal.siui.colors.fromToken(SiColor.SVG_NORMAL)).icons
22 | )
23 |
24 |
25 | class MySiliconApp(SiliconApplication):
26 | def __init__(self, *args, **kwargs):
27 | super().__init__(*args, **kwargs)
28 |
29 | screen_geo = QDesktopWidget().screenGeometry()
30 | self.setMinimumSize(1024, 380)
31 | self.resize(1366, 916)
32 | self.move((screen_geo.width() - self.width()) // 2, (screen_geo.height() - self.height()) // 2)
33 | self.layerMain().setTitle("Silicon UI Gallery")
34 | self.setWindowTitle("Silicon UI Gallery")
35 | self.setWindowIcon(QIcon("./img/empty_icon.png"))
36 |
37 | self.layerMain().addPage(ExampleHomepage(self),
38 | icon=SiGlobal.siui.iconpack.get("ic_fluent_home_filled"),
39 | hint="主页", side="top")
40 | self.layerMain().addPage(ExampleIcons(self),
41 | icon=SiGlobal.siui.iconpack.get("ic_fluent_diversity_filled"),
42 | hint="图标包", side="top")
43 | self.layerMain().addPage(RefactoredWidgets(self),
44 | icon=SiGlobal.siui.iconpack.get("ic_fluent_box_arrow_up_filled"),
45 | hint="重构控件", side="top")
46 | self.layerMain().addPage(ExampleWidgets(self),
47 | icon=SiGlobal.siui.iconpack.get("ic_fluent_box_multiple_filled"),
48 | hint="控件", side="top")
49 | self.layerMain().addPage(ExampleContainer(self),
50 | icon=SiGlobal.siui.iconpack.get("ic_fluent_align_stretch_vertical_filled"),
51 | hint="容器", side="top")
52 | self.layerMain().addPage(ExampleOptionCards(self),
53 | icon=SiGlobal.siui.iconpack.get("ic_fluent_list_bar_filled"),
54 | hint="选项卡", side="top")
55 | self.layerMain().addPage(ExampleDialogs(self),
56 | icon=SiGlobal.siui.iconpack.get("ic_fluent_panel_separate_window_filled"),
57 | hint="消息与二级界面", side="top")
58 | self.layerMain().addPage(ExamplePageControl(self),
59 | icon=SiGlobal.siui.iconpack.get("ic_fluent_wrench_screwdriver_filled"),
60 | hint="页面控制", side="top")
61 | self.layerMain().addPage(ExampleFunctional(self),
62 | icon=SiGlobal.siui.iconpack.get("ic_fluent_puzzle_piece_filled"),
63 | hint="功能组件", side="top")
64 |
65 | self.layerMain().addPage(About(self),
66 | icon=SiGlobal.siui.iconpack.get("ic_fluent_info_filled"),
67 | hint="关于", side="bottom")
68 |
69 | self.layerMain().setPage(0)
70 |
71 | SiGlobal.siui.reloadAllWindowsStyleSheet()
72 |
--------------------------------------------------------------------------------
/examples/My-TODOs/components/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/My-TODOs/components/__init__.py
--------------------------------------------------------------------------------
/examples/My-TODOs/components/core.py:
--------------------------------------------------------------------------------
1 | class Task:
2 | def __init__(self, name, description, due_time_stamp, color):
3 | self.name = name
4 | self.description = description
5 | self.due_time_stamp = due_time_stamp
6 | self.color = color
7 |
8 |
--------------------------------------------------------------------------------
/examples/My-TODOs/components/page_about/__init__.py:
--------------------------------------------------------------------------------
1 | from .page_about import About
--------------------------------------------------------------------------------
/examples/My-TODOs/components/page_about/page_about.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt, QUrl
2 | from PyQt5.QtGui import QDesktopServices
3 |
4 | from siui.components import (
5 | SiDenseVContainer,
6 | SiLabel,
7 | SiOptionCardLinear,
8 | SiPixLabel,
9 | SiSimpleButton,
10 | SiTitledWidgetGroup,
11 | )
12 | from siui.components.page import SiPage
13 | from siui.core import GlobalFont, Si, SiColor, SiGlobal, SiQuickEffect
14 | from siui.gui import SiFont
15 |
16 |
17 | class About(SiPage):
18 | def __init__(self, *args, **kwargs):
19 | super().__init__(*args, **kwargs)
20 |
21 | self.setPadding(64)
22 | self.setScrollMaximumWidth(950)
23 | self.setTitle("关于")
24 |
25 | self.titled_widget_group = SiTitledWidgetGroup(self)
26 | self.titled_widget_group.setSiliconWidgetFlag(Si.EnableAnimationSignals)
27 |
28 | version_picture_container = SiDenseVContainer(self)
29 | version_picture_container.setAlignment(Qt.AlignCenter)
30 | version_picture_container.setFixedHeight(128 + 48)
31 | SiQuickEffect.applyDropShadowOn(version_picture_container, color=(28, 25, 31, 255), blur_radius=48)
32 |
33 | self.version_picture = SiPixLabel(self)
34 | self.version_picture.setFixedSize(128, 128)
35 | self.version_picture.setBorderRadius(0)
36 | self.version_picture.load("./img/logo_new.png")
37 |
38 | self.version_label = SiLabel(self)
39 | self.version_label.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged)
40 | self.version_label.setFont(SiFont.tokenized(GlobalFont.M_NORMAL))
41 | self.version_label.setStyleSheet(f"color: {self.getColor(SiColor.TEXT_D)}")
42 | self.version_label.setText("PyQt-SiliconUI")
43 |
44 | version_picture_container.addWidget(self.version_picture)
45 | version_picture_container.addWidget(self.version_label)
46 | self.titled_widget_group.addWidget(version_picture_container)
47 |
48 | with self.titled_widget_group as group:
49 | group.addTitle("开源")
50 |
51 | self.button_to_repo = SiSimpleButton(self)
52 | self.button_to_repo.resize(32, 32)
53 | self.button_to_repo.attachment().load(SiGlobal.siui.iconpack.get("ic_fluent_open_regular"))
54 | self.button_to_repo.clicked.connect(lambda: QDesktopServices.openUrl(QUrl("https://github.com/ChinaIceF/PyQt-SiliconUI")))
55 |
56 | self.option_card_repo = SiOptionCardLinear(self)
57 | self.option_card_repo.setTitle("开源仓库", "在 GitHub 上查看 Silicon UI 的项目主页")
58 | self.option_card_repo.load(SiGlobal.siui.iconpack.get("ic_fluent_home_database_regular"))
59 | self.option_card_repo.addWidget(self.button_to_repo)
60 |
61 | self.option_card_license = SiOptionCardLinear(self)
62 | self.option_card_license.setTitle("开源许可证", "本项目遵循 GPLv3.0 许可证供非商业使用")
63 | self.option_card_license.load(SiGlobal.siui.iconpack.get("ic_fluent_certificate_regular"))
64 |
65 | group.addWidget(self.option_card_repo)
66 | group.addWidget(self.option_card_license)
67 |
68 | with self.titled_widget_group as group:
69 | group.addTitle("版权")
70 |
71 | self.option_card_copyright = SiOptionCardLinear(self)
72 | self.option_card_copyright.setTitle("版权声明", "PyQt-SiliconUI 版权所有 © 2024 by ChinaIceF")
73 | self.option_card_copyright.load(SiGlobal.siui.iconpack.get("ic_fluent_info_regular"))
74 |
75 | group.addWidget(self.option_card_copyright)
76 |
77 | with self.titled_widget_group as group:
78 | group.addTitle("第三方资源")
79 |
80 | self.option_card_icon_pack = SiOptionCardLinear(self)
81 | self.option_card_icon_pack.setTitle("Fluent UI 图标库", "本项目内置了 Fluent UI 图标库,Microsoft 公司保有这些图标的版权")
82 | self.option_card_icon_pack.load(SiGlobal.siui.iconpack.get("ic_fluent_diversity_regular"))
83 |
84 | group.addWidget(self.option_card_icon_pack)
85 |
86 | # add placeholder for better outfit
87 | self.titled_widget_group.addPlaceholder(64)
88 |
89 | # Set SiTitledWidgetGroup object as the attachment of the page's scroll area
90 | self.setAttachment(self.titled_widget_group)
91 |
--------------------------------------------------------------------------------
/examples/My-TODOs/components/page_homepage/__init__.py:
--------------------------------------------------------------------------------
1 | from .homepage import Homepage
--------------------------------------------------------------------------------
/examples/My-TODOs/components/page_homepage/components/__init__.py:
--------------------------------------------------------------------------------
1 | from .today import TodayMainWidget
--------------------------------------------------------------------------------
/examples/My-TODOs/components/page_homepage/homepage.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | from PyQt5.QtCore import Qt
4 |
5 | from siui.components import SiTitledWidgetGroup, SiPixLabel, SiDenseVContainer
6 | from siui.components.page import SiPage
7 | from siui.core import Si, SiColor
8 |
9 | from ..core import Task
10 | from ..widgets import SmallGroupTitle, TaskCardLinear
11 | from .components import TodayMainWidget
12 |
13 |
14 | class SmallTitledWidgetGroup(SiTitledWidgetGroup):
15 | def addTitle(self, title):
16 |
17 | if len(self.widgets_top) > 0:
18 | self.addPlaceholder(16)
19 |
20 | new_title = SmallGroupTitle(self)
21 | new_title.setTitle(title)
22 | self.addWidget(new_title)
23 |
24 |
25 | class Homepage(SiPage):
26 | def __init__(self, *args, **kwargs):
27 | super().__init__(*args, **kwargs)
28 |
29 | self.setPadding(0)
30 | self.setScrollMaximumWidth(10000)
31 | # self.setTitle("主页")
32 |
33 | self.head_pic_and_content = SiDenseVContainer(self)
34 | self.head_pic_and_content.setAlignment(Qt.AlignHCenter)
35 | self.head_pic_and_content.setSpacing(0)
36 |
37 | self.background_image = SiPixLabel(self)
38 | self.background_image.load("./images/default_background.png")
39 | self.background_image.setFixedHeight(320)
40 | self.background_image.setBorderRadius(6)
41 |
42 | self.titled_widget_group = SmallTitledWidgetGroup(self)
43 | self.titled_widget_group.setSiliconWidgetFlag(Si.EnableAnimationSignals)
44 | self.titled_widget_group.addPlaceholder(32)
45 |
46 | with self.titled_widget_group as group:
47 | #group.addTitle("时间线")
48 |
49 | self.today_main_widget = TodayMainWidget(self)
50 | self.today_main_widget.adjustSize()
51 |
52 | group.addPlaceholder(16)
53 | group.addWidget(self.today_main_widget)
54 |
55 | self.titled_widget_group.addPlaceholder(32)
56 |
57 | with self.titled_widget_group as group:
58 | group.addTitle("待办详情")
59 |
60 | self.test_task_card = TaskCardLinear(Task("上床睡觉", "闭上眼睛直接睡觉就行", time.time(), self.getColor(SiColor.PROGRESS_BAR_COMPLETING)), parent=self)
61 | self.test_task_card.resize(0, 80)
62 |
63 | self.test_task_card2 = TaskCardLinear(Task("写数学作业", "不写完作业该怎么交作业呢", time.time(), self.getColor(SiColor.PROGRESS_BAR_PROCESSING)), parent=self)
64 | self.test_task_card2.resize(0, 80)
65 |
66 | group.addPlaceholder(16)
67 | group.addWidget(self.test_task_card)
68 | group.addWidget(self.test_task_card2)
69 |
70 | self.titled_widget_group.addPlaceholder(64)
71 |
72 | self.head_pic_and_content.addWidget(self.background_image)
73 | self.head_pic_and_content.addWidget(self.titled_widget_group)
74 |
75 | self.setAttachment(self.head_pic_and_content)
76 |
77 | def resizeEvent(self, event):
78 | super().resizeEvent(event)
79 | self.background_image.resize(event.size().width(), 200)
80 | self.titled_widget_group.resize(event.size().width() - 128, self.titled_widget_group.height())
81 | self.head_pic_and_content.arrangeWidget()
82 |
--------------------------------------------------------------------------------
/examples/My-TODOs/components/widgets/__init__.py:
--------------------------------------------------------------------------------
1 | from .group_title import SmallGroupTitle
2 | from .tasks import TaskCardLinear
3 | from .button import RectButtonWithIconAndDescription
--------------------------------------------------------------------------------
/examples/My-TODOs/components/widgets/button.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtGui import QFont
2 |
3 | from siui.components import SiLabel, SiSimpleButton, SiSvgLabel, SiWidget
4 | from siui.core import SiColor, SiGlobal
5 | from siui.gui import SiFont
6 |
7 |
8 | class RectButtonWithIconAndDescription(SiWidget):
9 | def __init__(self, title, description, icon_name, parent=None):
10 | super().__init__(parent)
11 |
12 | self.panel = SiLabel(self)
13 | self.panel.setFixedStyleSheet("border-radius: 4px")
14 | self.panel.setColor(self.getColor(SiColor.INTERFACE_BG_C))
15 |
16 | self.icon_circle = SiLabel(self)
17 | self.icon_circle.setFixedSize(32, 32)
18 | self.icon_circle.move(20, 24)
19 | self.icon_circle.setFixedStyleSheet("border-radius: 16px")
20 | self.icon_circle.setColor(self.getColor(SiColor.INTERFACE_BG_D))
21 |
22 | self.icon = SiSvgLabel(self.icon_circle)
23 | self.icon.resize(32, 32)
24 | self.icon.load(SiGlobal.siui.iconpack.get(icon_name, color_code=self.getColor(SiColor.SVG_NORMAL)))
25 | self.icon.setSvgSize(16, 16)
26 |
27 | self.title = SiLabel(self)
28 | self.title.setFont(SiFont.getFont(size=16, weight=QFont.Weight.Bold))
29 | self.title.setTextColor(self.getColor(SiColor.TEXT_B))
30 | self.title.setText(title)
31 | self.title.adjustSize()
32 | self.title.move(72, 20)
33 |
34 | self.description = SiLabel(self)
35 | self.description.setFont(SiFont.getFont(size=14, weight=QFont.Weight.Light))
36 | self.description.setTextColor(self.getColor(SiColor.TEXT_D))
37 | self.description.setText(description)
38 | self.description.adjustSize()
39 | self.description.move(72, 20 + 20)
40 |
41 | self.button_ = SiSimpleButton(self)
42 | self.button_.setBorderRadius(4)
43 |
44 | def button(self):
45 | return self.button_
46 |
47 | def resizeEvent(self, event):
48 | super().resizeEvent(event)
49 | self.panel.resize(event.size())
50 | self.button_.resize(event.size())
51 |
--------------------------------------------------------------------------------
/examples/My-TODOs/components/widgets/group_title.py:
--------------------------------------------------------------------------------
1 | from PyQt5.Qt import QFont
2 |
3 | from siui.components import SiLabel, SiWidget
4 | from siui.core import SiColor
5 | from siui.gui import SiFont
6 |
7 |
8 | class SmallGroupTitle(SiWidget):
9 | def __init__(self, *args, **kwargs):
10 | super().__init__(*args, **kwargs)
11 | self.title = SiLabel(self)
12 | self.title.setFont(SiFont.getFont(size=16, weight=QFont.Weight.Bold))
13 |
14 | self.title_indicator = SiLabel(self)
15 | self.title_indicator.setFixedStyleSheet("border-radius: 1px")
16 |
17 | def reloadStyleSheet(self):
18 | super().reloadStyleSheet()
19 | self.title.setTextColor(self.getColor(SiColor.TEXT_B))
20 | self.title_indicator.setColor(self.getColor(SiColor.TITLE_INDICATOR))
21 |
22 | def setTitle(self, title):
23 | self.title.setText(title)
24 | self.title.adjustSize()
25 | self.adjustSize()
26 |
27 | def adjustSize(self):
28 | self.resize(self.title.width(), self.title.height() + 8)
29 | self.title_indicator.setGeometry(0, self.height() - 3, self.width(), 3)
30 |
--------------------------------------------------------------------------------
/examples/My-TODOs/components/widgets/tasks.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtGui import QFont
2 |
3 | from siui.components import SiLabel, SiWidget
4 | from siui.core import SiColor
5 | from siui.gui import SiFont
6 |
7 | from ..core import Task
8 |
9 |
10 | class TaskCardLinear(SiWidget):
11 | def __init__(self, task, parent=None):
12 | super().__init__(parent)
13 | self.task = None
14 |
15 | self.theme_color_indicator = SiLabel(self)
16 | self.theme_color_indicator.setFixedStyleSheet("border-radius: 8px")
17 |
18 | self.original_panel = SiLabel(self)
19 | self.original_panel.setFixedStyleSheet("border-radius: 8px")
20 | self.original_panel.setColor(self.getColor(SiColor.INTERFACE_BG_C))
21 |
22 | self.panel = SiLabel(self)
23 | self.panel.setFixedStyleSheet("border-radius: 8px; border-top-left-radius: 6px; border-bottom-left-radius: 6px")
24 |
25 | self.title = SiLabel(self)
26 | self.title.setFont(SiFont.getFont(size=18, weight=QFont.Weight.Bold))
27 |
28 | self.description = SiLabel(self)
29 | self.description.setFont(SiFont.getFont(size=14, weight=QFont.Weight.Normal))
30 |
31 | self.loadTask(task)
32 |
33 | def loadTask(self, task: Task):
34 | self.task = task
35 | self.theme_color_indicator.setColor(task.color)
36 | self.panel.setColor(SiColor.mix(self.getColor(SiColor.INTERFACE_BG_C), task.color, weight=0.9))
37 | self.title.setTextColor(self.getColor(SiColor.TEXT_B))
38 | self.description.setTextColor(SiColor.mix(self.getColor(SiColor.TEXT_B), task.color))
39 |
40 | self.title.setText(task.name)
41 | self.description.setText(task.description)
42 |
43 | def getTask(self):
44 | return self.task
45 |
46 | def resizeEvent(self, event):
47 | super().resizeEvent(event)
48 | self.theme_color_indicator.resize(48, event.size().height())
49 | self.original_panel.setGeometry(24, 0, event.size().width() - 24, event.size().height())
50 | self.panel.setGeometry(24, 0, event.size().width() - 24 - 60, event.size().height())
51 | self.title.move(80, 18)
52 | self.description.move(80, 18 + 24)
53 |
--------------------------------------------------------------------------------
/examples/My-TODOs/icons/__init__.py:
--------------------------------------------------------------------------------
1 | from .parser import *
2 |
--------------------------------------------------------------------------------
/examples/My-TODOs/icons/icons.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/My-TODOs/icons/icons.dat
--------------------------------------------------------------------------------
/examples/My-TODOs/icons/parser.py:
--------------------------------------------------------------------------------
1 | import numpy
2 | import os
3 |
4 | current_module_path = os.path.dirname(os.path.abspath(__file__))
5 | data_file_path = os.path.join(current_module_path, './icons.dat')
6 |
7 | class IconDictionary:
8 | def __init__(self, library_path=data_file_path, color=None):
9 |
10 | # !注意! 你不应使用这些文件,他们已经过加密处理
11 | # 如果你需要这些图标文件,你可以直接在 flaticon.com 免费获取他们
12 |
13 | # 读取数据并解密
14 | f = open(library_path, 'rb')
15 | library_raw = f.read()
16 | library_list = list(library_raw)
17 | library = bytes(list((numpy.array(library_list) + numpy.array(range(len(library_list))) * 17) % 255)).decode() # 解密
18 |
19 | # 整理成字典
20 | items = library.split('!!!')
21 | names = []
22 | datas = []
23 | for item in items[1:]:
24 | name, data = item.split('###')
25 | data = data.replace('/>', ' fill="{}" />'.format(color))
26 | names.append(name)
27 | datas.append(data.encode())
28 | self.icons = dict(zip(names, datas))
29 |
30 | def get(self, name):
31 | svg_data = self.icons[name]
32 | return svg_data.encode()
33 |
--------------------------------------------------------------------------------
/examples/My-TODOs/images/default_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/examples/My-TODOs/images/default_background.png
--------------------------------------------------------------------------------
/examples/My-TODOs/start.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from PyQt5.QtWidgets import QApplication
3 | from ui import MySiliconApp
4 |
5 |
6 | if __name__ == "__main__":
7 | app = QApplication(sys.argv)
8 |
9 | window = MySiliconApp()
10 | window.show()
11 |
12 | sys.exit(app.exec_())
13 |
--------------------------------------------------------------------------------
/examples/My-TODOs/ui.py:
--------------------------------------------------------------------------------
1 | import icons
2 | from components.page_about import About
3 | from components.page_homepage import Homepage
4 | from PyQt5.QtGui import QIcon
5 | from PyQt5.QtWidgets import QDesktopWidget
6 |
7 | import siui
8 | from siui.core import SiColor, SiGlobal
9 | from siui.templates.application.application import SiliconApplication
10 |
11 | # 载入图标
12 | siui.core.globals.SiGlobal.siui.loadIcons(
13 | icons.IconDictionary(color=SiGlobal.siui.colors.fromToken(SiColor.SVG_NORMAL)).icons
14 | )
15 |
16 |
17 | class MySiliconApp(SiliconApplication):
18 | def __init__(self, *args, **kwargs):
19 | super().__init__(*args, **kwargs)
20 |
21 | screen_geo = QDesktopWidget().screenGeometry()
22 | self.setMinimumSize(1024, 380)
23 | self.resize(1366, 916)
24 | self.move((screen_geo.width() - self.width()) // 2, (screen_geo.height() - self.height()) // 2)
25 | self.layerMain().setTitle("My-TODOs")
26 | self.setWindowTitle("My-TODOs")
27 | self.setWindowIcon(QIcon("./img/empty_icon.png"))
28 |
29 | self.layerMain().addPage(Homepage(self),
30 | icon=SiGlobal.siui.iconpack.get("ic_fluent_home_filled"),
31 | hint="主页", side="top")
32 |
33 | self.layerMain().addPage(About(self),
34 | icon=SiGlobal.siui.iconpack.get("ic_fluent_info_filled"),
35 | hint="关于", side="bottom")
36 |
37 | self.layerMain().setPage(0)
38 |
39 | SiGlobal.siui.reloadAllWindowsStyleSheet()
40 |
--------------------------------------------------------------------------------
/examples/button/demo_button.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton
3 |
4 | from SiliconUI.SiButton import SiButton, SiButtonHoldtoConfirm
5 | from SiliconUI.SiLayout import SiLayoutV
6 | from SiliconUI.SiGlobal import colorset
7 |
8 | # 当按钮点击事件触发时
9 | def when_button_clicked():
10 | print('Clicked.')
11 |
12 | # 当按钮按下状态改变时
13 | def when_button_holdstatechanged(state):
14 | print('Hold state changed.', state)
15 |
16 |
17 | class ButtonExample(QWidget):
18 | def __init__(self):
19 | super().__init__()
20 |
21 | # 初始化窗口
22 | self.initUI()
23 |
24 | def initUI(self):
25 |
26 | # 创建垂直布局
27 | self.layout = SiLayoutV(self)
28 | self.layout.setFixedWidth(128)
29 | self.layout.setAlignment(Qt.AlignCenter) # 设置元素居中
30 |
31 | # 创建三个按钮
32 | btn1 = SiButton(self.layout)
33 | btn1.resize(128, 32)
34 | btn1.setText('普通按钮')
35 | btn1.clicked.connect(when_button_clicked)
36 | btn1.holdStateChanged.connect(when_button_holdstatechanged)
37 |
38 | btn2 = SiButton(self.layout)
39 | btn2.resize(128, 32)
40 | btn2.setText('高亮按钮')
41 | btn2.clicked.connect(when_button_clicked)
42 | btn2.holdStateChanged.connect(when_button_holdstatechanged)
43 |
44 | btn3 = SiButtonHoldtoConfirm(self.layout)
45 | btn3.resize(128, 32)
46 | btn3.setText('长按按钮')
47 | btn3.clicked.connect(when_button_clicked)
48 | btn3.holdStateChanged.connect(when_button_holdstatechanged)
49 |
50 | # 将按钮添加到垂直布局中
51 | self.layout.addItem(btn1)
52 | self.layout.addItem(btn2)
53 | self.layout.addItem(btn3)
54 |
55 | # 设置布局位置
56 | self.layout.move(96, 64)
57 |
58 | # 设置窗口属性
59 | self.setWindowTitle('SiliconUI.SiButton 三类按钮实例')
60 | self.setStyleSheet('background-color: {}'.format(colorset.BG_GRAD_HEX[2]))
61 | self.setGeometry(300, 300, 320, 256)
62 |
63 | if __name__ == '__main__':
64 |
65 | app = QApplication(sys.argv)
66 | ex = ButtonExample()
67 | ex.show()
68 | sys.exit(app.exec_())
69 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "PyQt-SiliconUI"
3 | version = "1.0.1"
4 | authors = [
5 | { name = "ChinaIceF", email = "ChinaIceF@outlook.com" },
6 | { name = "rainzee wang", email = "rainzee.w@gmail.com" },
7 | ]
8 | description = "A powerful and artistic UI library based on PyQt5 / PySide6"
9 | readme = "README.md"
10 | license = { file = "LICENSE" }
11 | requires-python = ">=3.8"
12 | dependencies = ["PyQt5>=5.15.10", "typing-extensions>=4.12.2", "python-dateutil>=2.9.0"]
13 |
14 | [project.urls]
15 | Repository = "https://github.com/ChinaIceF/PyQt-SiliconUI"
16 |
17 | [tool.pdm.dev-dependencies]
18 | stub = ["pyqt5-stubs>=5.15.6.0"]
19 | lint = ["ruff>=0.5.0"]
20 | build = ["nuitka>=2.3.10"]
21 | profile = ["viztracer>=0.16.3"]
22 |
23 | [tool.ruff]
24 | line-length = 120
25 | target-version = "py38"
26 |
27 | [tool.ruff.lint]
28 | select = ["I", "E", "W", "F", "C", "Q", "PT", "UP", "PYI", "T20"]
29 |
30 | [tool.pyright]
31 | pythonVersion = "3.8"
32 | pythonPlatform = "All"
33 | typeCheckingMode = "standard"
34 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import find_packages, setup
2 |
3 | # 定义项目需要的依赖项
4 | install_requires = [
5 | "PyQt5>=5.15.10",
6 | "numpy",
7 | "pyperclip",
8 | ]
9 |
10 | # 定义项目元数据
11 | setup(
12 | name = "PyQt-SiliconUI",
13 | version = "1.01",
14 | packages = find_packages(exclude = ["examples"]), # 自动找到所有包
15 | data_files=[("./siui/gui/icons/packages", ["./siui/gui/icons/packages/fluent_ui_icon_filled.icons",
16 | "./siui/gui/icons/packages/fluent_ui_icon_regular.icons",
17 | "./siui/gui/icons/packages/fluent_ui_icon_light.icons"]),],
18 | include_package_data = True,
19 | install_requires = install_requires, # 依赖项列表
20 | # 以下为可选元数据
21 | description = "A powerful and artistic UI library based on PyQt5 / PySide6", # 包的简短描述
22 | long_description = open("README.md", encoding="utf-8").read(), # 包的详细描述,通常来自README文件
23 | long_description_content_type = "text/markdown", # README文件的格式
24 | url = "https://github.com/ChinaIceF/PyQt-SiliconUI", # 项目主页
25 | author = "ChinaIceF", # 作者名
26 | author_email = "ChinaIceF@outlook.com", # 作者邮箱
27 | license = "GPL-3.0", # 许可证
28 | classifiers=[ # 项目的分类信息
29 | "Development Status :: 3 - Alpha",
30 | "Intended Audience :: Developers",
31 | "License :: OSI Approved :: GPL-3.0 License",
32 | "Programming Language :: Python :: 3",
33 | "Programming Language :: Python :: 3.6",
34 | "Programming Language :: Python :: 3.7",
35 | "Programming Language :: Python :: 3.8",
36 | "Programming Language :: Python :: 3.9",
37 | "Programming Language :: Python :: 3.10",
38 | "Programming Language :: Python :: 3.11",
39 | "Programming Language :: Python :: 3.12",
40 | "Topic :: Software Development :: Libraries :: Python Modules",
41 | ],
42 | entry_points={ # 如果包是可执行的,定义入口点
43 | "console_scripts": [
44 | ""
45 | ],
46 | },
47 | )
48 |
--------------------------------------------------------------------------------
/siui/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | import siui
4 | import siui.components as components
5 | import siui.components.widgets as widgets
6 | import siui.core as core
7 | import siui.core.globals
8 | import siui.gui as gui
9 | import siui.templates as templates
10 |
11 | # 加载全局缩放比例
12 | siui.gui.scale.reload_scale_factor()
13 |
--------------------------------------------------------------------------------
/siui/components/__init__.py:
--------------------------------------------------------------------------------
1 | from siui.components.option_card import *
2 | from siui.components.progress_bar import *
3 | # from siui.components.slider import *
4 | from siui.components.titled_widget_group import *
5 | from siui.components.widgets import *
6 |
--------------------------------------------------------------------------------
/siui/components/combobox/__init__.py:
--------------------------------------------------------------------------------
1 | from siui.components.combobox.combobox import SiComboBox
--------------------------------------------------------------------------------
/siui/components/menu/__init__.py:
--------------------------------------------------------------------------------
1 | from siui.components.menu.menu import SiMenuOption, SiMenu
--------------------------------------------------------------------------------
/siui/components/menu/abstracts/__init__.py:
--------------------------------------------------------------------------------
1 | from siui.components.menu.abstracts.menu import ABCSiMenu
2 | from siui.components.menu.abstracts.ani_manager import AnimationManager
--------------------------------------------------------------------------------
/siui/components/menu/menu.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt, pyqtSignal, QSize
2 | from PyQt5.QtGui import QColor
3 | from PyQt5.QtWidgets import QGraphicsDropShadowEffect
4 |
5 | from siui.components import SiWidget, SiLabel, SiDenseVContainer
6 | from siui.components.menu.abstracts import ABCSiMenu, AnimationManager
7 | from siui.components.menu.option import SiMenuOption
8 | from siui.core import SiQuickEffect, SiColor, SiGlobal
9 |
10 |
11 | class SiMenu(ABCSiMenu):
12 | def __init__(self, *args, **kwargs):
13 | super().__init__(*args, **kwargs)
14 | self.setAnimationManager(AnimationManager.PULL_DOWN)
15 |
16 | def addOption(self,
17 | text: str,
18 | value=None,
19 | icon=None,
20 | child_menu=None):
21 | new_option = SiMenuOption(self, child_menu, text, value=value, icon=icon)
22 | new_option.setSelectable(self.is_selection_menu)
23 | new_option.setFixedHeight(32)
24 |
25 | self.options_.append(new_option)
26 | self.body().addWidget(new_option)
27 | self.body().arrangeWidget()
28 |
29 |
30 | class SiInteractionMenu(SiWidget):
31 | indexChanged = pyqtSignal(int)
32 | valueChanged = pyqtSignal(object)
33 | unfoldSignal = pyqtSignal()
34 | closeSignal = pyqtSignal()
35 |
36 | def __init__(self, *args, **kwargs):
37 | super().__init__(*args, **kwargs)
38 |
39 | # 在窗口列表里注册菜单,用于重载样式表
40 | SiGlobal.siui.windows[str(self)] = self
41 |
42 | self.animation_manager = None
43 | self.margin = 32
44 | self.padding = 4
45 |
46 | self.setAnimationManager(AnimationManager.PULL_DOWN)
47 |
48 | self.setMoveAnchor(self.margin + self.padding, self.margin + self.padding)
49 | self.setMinimumSize(self.margin*2, self.margin*2)
50 | self.setAttribute(Qt.WA_TranslucentBackground)
51 | self.setWindowFlags(Qt.Popup | Qt.FramelessWindowHint | Qt.NoDropShadowWindowHint)
52 |
53 | self.body_frame = SiWidget(self)
54 |
55 | self.body_panel = SiLabel(self.body_frame)
56 | self.body_panel.setObjectName("menu_body_panel")
57 |
58 | self.flash_layer = SiLabel(self)
59 | self.flash_layer.setFixedStyleSheet("border-radius: 6px")
60 | self.flash_layer.setAttribute(Qt.WA_TransparentForMouseEvents)
61 | self.flash_layer.animationGroup().fromToken("color").setFactor(1/16)
62 |
63 | self.body_ = SiDenseVContainer(self.body_panel)
64 | self.body_.setAdjustWidgetsSize(True)
65 | self.body_.setSpacing(2)
66 | self.body_.resize(0, 0)
67 |
68 | SiQuickEffect.applyDropShadowOn(self.body_frame, (0, 0, 0, 80), (0, 0), 32)
69 |
70 | def reloadStyleSheet(self):
71 | super().reloadStyleSheet()
72 | self.body_panel.setStyleSheet(
73 | f"""#menu_body_panel {{
74 | background-color: {self.getColor(SiColor.MENU_BG)};
75 | border: 1px solid {SiColor.mix(self.getColor(SiColor.MENU_BG), self.getColor(SiColor.TEXT_E), 0.9)};
76 | border-radius: 6px
77 | }}"""
78 | )
79 |
80 | def setAnimationManager(self, token):
81 | self.animation_manager = token.value
82 |
83 | def animationManager(self):
84 | return self.animation_manager
85 |
86 | def unfold(self, x, y):
87 | """ unfold the menu """
88 | self.animationManager().on_parent_unfolded(self, x, y)
89 | SiGlobal.siui.windows["TOOL_TIP"].raise_()
90 |
91 | def setContentFixedWidth(self, w):
92 | self.setFixedWidth(w + self.padding*2 + self.margin*2)
93 |
94 | def closeEvent(self, a0):
95 | super().closeEvent(a0)
96 | self.closeSignal.emit()
97 | self.resize(self.width(), self.margin * 2)
98 |
99 | def resizeEvent(self, event):
100 | self.animationManager().on_parent_resized(self, event)
101 | super().resizeEvent(event)
102 |
103 | def sizeHint(self):
104 | w = self.body_.sizeHint().width() + 2 * self.padding + 2 * self.margin
105 | h = self.body_.sizeHint().height() + 2 * self.padding + 2 * self.margin
106 | return QSize(w, h)
107 |
108 |
--------------------------------------------------------------------------------
/siui/components/option_card/__init__.py:
--------------------------------------------------------------------------------
1 | from siui.components.option_card.option_card import *
2 | import siui.components.option_card.abstracts as abstracts
--------------------------------------------------------------------------------
/siui/components/option_card/abstracts/__init__.py:
--------------------------------------------------------------------------------
1 | from siui.components.option_card.abstracts.option_card import ABCSiOptionCardPlane
--------------------------------------------------------------------------------
/siui/components/option_card/abstracts/option_card.py:
--------------------------------------------------------------------------------
1 | from siui.components.widgets import SiDenseHContainer, SiDenseVContainer, SiLabel
2 | from siui.core import SiGlobal
3 |
4 |
5 | class ABCSiOptionCardPlane(SiLabel):
6 | """
7 | 平面型选项卡,划分 header, body, footer,为一般场景提供支持
8 | """
9 | def __init__(self, *args, **kwargs):
10 | super().__init__(*args, **kwargs)
11 |
12 | self.spacing_ = 24
13 |
14 | # 构建组成外观的控件
15 | self.outfit_label_lower = SiLabel(self)
16 | self.outfit_label_lower.setFixedStyleSheet("border-radius: 6px")
17 |
18 | self.outfit_label_upper = SiLabel(self)
19 | self.outfit_label_upper.setFixedStyleSheet("border-radius: 6px")
20 |
21 | # 创建容器
22 | self.container = SiDenseVContainer(self)
23 | self.container.setSpacing(0)
24 | self.container.setAdjustWidgetsSize(True)
25 |
26 | # 创建划分区域
27 | self.header_ = SiDenseHContainer(self)
28 | self.header_.resize(0, 0)
29 |
30 | self.body_ = SiDenseVContainer(self) # 只有 body 是竖直密堆积容器
31 | self.body_.setSpacing(8)
32 | self.body_.resize(0, 0)
33 |
34 | self.footer_ = SiDenseHContainer(self)
35 | self.footer_.resize(0, 0)
36 |
37 | # 设置子控件适应容器,并把三个组成部分添加到自己
38 |
39 | self.container.addWidget(self.header_)
40 | self.container.addWidget(self.body_)
41 | self.container.addWidget(self.footer_, "bottom")
42 |
43 | def setSpacing(self, spacing):
44 | """
45 | 设置容器与边缘左右的间隔
46 | :param spacing: 间隔
47 | """
48 | self.spacing_ = spacing
49 |
50 | def spacing(self):
51 | """
52 | 获取容器与边缘左右的间隔
53 | :return: 间隔
54 | """
55 | return self.spacing_
56 |
57 | def header(self):
58 | """
59 | 返回 header 容器
60 | :return: header 容器
61 | """
62 | return self.header_
63 |
64 | def body(self):
65 | """
66 | 返回 body 容器
67 | :return: body 容器
68 | """
69 | return self.body_
70 |
71 | def footer(self):
72 | """
73 | 返回 footer 容器
74 | :return: footer 容器
75 | """
76 | return self.footer_
77 |
78 | def adjustSize(self):
79 | self.resize(self.width(), self.header().height() + self.body().height() + self.footer().height() + 3)
80 |
81 | def reloadStyleSheet(self):
82 | super().reloadStyleSheet()
83 |
84 | self.outfit_label_lower.setStyleSheet("background-color: {}".format(SiGlobal.siui.colors["INTERFACE_BG_A"]))
85 | self.outfit_label_upper.setStyleSheet("background-color: {}".format(SiGlobal.siui.colors["INTERFACE_BG_C"]))
86 |
87 | def resizeEvent(self, event):
88 | super().resizeEvent(event)
89 | size = event.size()
90 | w, h = size.width(), size.height()
91 |
92 | self.container.setGeometry(self.spacing(), 0, w-self.spacing()*2, h-3)
93 |
94 | self.outfit_label_lower.setGeometry(0, 8, w, h-8) # 防止上边出现底色毛边
95 | self.outfit_label_upper.resize(w, h - 3)
96 |
--------------------------------------------------------------------------------
/siui/components/option_card/option_card.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt
2 |
3 | from siui.components.option_card.abstracts.option_card import ABCSiOptionCardPlane
4 | from siui.components.widgets.abstracts.widget import SiWidget
5 | from siui.components.widgets.container import SiDenseHContainer
6 | from siui.components.widgets.label import SiLabel, SiSvgLabel
7 | from siui.core import GlobalFont, Si, SiGlobal
8 | from siui.gui import SiFont
9 |
10 |
11 | class SiOptionCardLinear(SiWidget):
12 | def __init__(self, *args, **kwargs):
13 | super().__init__(*args, **kwargs)
14 |
15 | self.panel = SiLabel(self)
16 | self.panel.setFixedStyleSheet(f"background-color:{SiGlobal.siui.colors['INTERFACE_BG_C']}; border-radius:4px")
17 |
18 | # 设定最小高度
19 | self.setMinimumHeight(80)
20 |
21 | # 创建整体容器
22 | self.container = SiDenseHContainer(self)
23 | self.container.setSpacing(0)
24 | self.container.setAlignment(Qt.AlignCenter)
25 | self.container.setAdjustWidgetsSize(True)
26 |
27 | # 开始从左到右构建所需控件
28 | # svg图标
29 | self.svg_icon = SiSvgLabel(self)
30 | self.svg_icon.setSvgSize(24, 24)
31 | self.svg_icon.resize(80, 80)
32 |
33 | # 文字标签
34 | self.text_label = SiLabel(self)
35 | self.text_label.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged)
36 | self.text_label.setFixedStyleSheet("padding-top: 20px; padding-bottom: 20px;")
37 |
38 | # 控件紧密排列容器
39 | self.widgets_container = SiDenseHContainer(self)
40 | self.widgets_container.setAlignment(Qt.AlignCenter)
41 | self.widgets_container.resize(0, 0)
42 |
43 | # 添加到整体容器中
44 | self.container.addWidget(self.svg_icon)
45 | self.container.addWidget(self.text_label)
46 |
47 | self.container.addPlaceholder(28, "right") # 防止控件和右侧边缘紧贴
48 | self.container.addWidget(self.widgets_container, "right")
49 | self.container.addPlaceholder(16, "right") # 防止文字和控件紧贴
50 |
51 | def reloadStyleSheet(self):
52 | super().reloadStyleSheet()
53 |
54 | def setTitle(self, title, subtitle=""):
55 | """
56 | 为选项卡设置文字
57 | :param title: 选项卡标题
58 | :param subtitle: 选项卡副标题
59 | :return:
60 | """
61 | # 根据是否有副标题,设置两种文字显示方式
62 | if subtitle == "":
63 | self.text_label.setText("{}".format(SiGlobal.siui.colors["TEXT_A"], title))
64 |
65 | else:
66 | subtitle = subtitle.replace("\n", "
")
67 | self.text_label.setText("{}
{}".format(
68 | SiGlobal.siui.colors["TEXT_A"], title, SiGlobal.siui.colors["TEXT_C"], subtitle))
69 |
70 | self.adjustSize()
71 |
72 | def setText(self, text: str):
73 | raise AttributeError("请使用 setTitle 方法设置选项卡文字")
74 |
75 | def load(self, path_or_data):
76 | """
77 | 加载图标
78 | :param path_or_data: svg 文件路径或 svg 数据
79 | :return:
80 | """
81 | self.svg_icon.load(path_or_data)
82 |
83 | def addWidget(self, widget):
84 | """
85 | 添加控件于选项卡右侧,这将改变控件的父对象
86 | :param widget: 控件
87 | :return:
88 | """
89 | self.widgets_container.addWidget(widget, "right")
90 |
91 | def adjustSize(self):
92 | self.container.resize(self.container.width(), self.text_label.height())
93 | self.container.adjustSize()
94 | self.resize(self.container.size())
95 |
96 | def resizeEvent(self, event):
97 | super().resizeEvent(event)
98 | w, h = event.size().width(), event.size().height()
99 |
100 | self.panel.resize(w, h)
101 | self.container.resize(w, h)
102 |
103 | # 让文字标签充满闲置区域
104 | spare_space = self.container.getSpareSpace()
105 | self.text_label.setFixedWidth(spare_space + self.text_label.width())
106 |
107 | # 确保其所有控件都在中轴线上,需要调用调整尺寸方法
108 | self.container.adjustSize()
109 |
110 |
111 | class SiOptionCardPlane(ABCSiOptionCardPlane):
112 | """
113 | 平面式选项卡。相较于其抽象类,此类提供
114 | """
115 | def __init__(self, *args, **kwargs):
116 | super().__init__(*args, **kwargs)
117 |
118 | # 在 header 创建标题
119 | self.title = SiLabel(self)
120 | self.title.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged)
121 | self.title.setFont(SiFont.tokenized(GlobalFont.M_BOLD))
122 | self.title.setAlignment(Qt.AlignVCenter | Qt.AlignLeft)
123 | self.title.setFixedHeight(32)
124 |
125 | self.header().setAlignment(Qt.AlignCenter)
126 | self.header().setFixedHeight(64)
127 | self.header().addWidget(self.title, "left")
128 |
129 | def reloadStyleSheet(self):
130 | super().reloadStyleSheet()
131 | self.title.setStyleSheet("color: {}".format(SiGlobal.siui.colors["TEXT_A"]))
132 |
133 | def setTitle(self, text: str):
134 | """
135 | 设置标题
136 | :param text: 标题
137 | :return:
138 | """
139 | self.title.setText(text)
140 |
--------------------------------------------------------------------------------
/siui/components/page/__init__.py:
--------------------------------------------------------------------------------
1 | from siui.components.page.page import *
--------------------------------------------------------------------------------
/siui/components/page/child_page.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt
2 |
3 | from siui.components import SiWidget, SiDenseHContainer, SiLabel, SiTitledWidgetGroup
4 | from siui.components.page import SiPage
5 | from siui.core import SiColor
6 | from siui.core import SiQuickEffect
7 | from siui.core import Si
8 |
9 |
10 | class SiChildPage(SiWidget):
11 | def __init__(self, *args, **kwargs):
12 | super().__init__(*args, **kwargs)
13 |
14 | self.width_ratio = 0.618
15 | self.height_ratio = (1-0.618) * 2
16 |
17 | self.view_ = SiWidget(self)
18 |
19 | # content
20 | self.background_content = SiLabel(self.view_)
21 | self.background_content.setStyleSheet(
22 | "border-radius: 8px;"
23 | f"background-color: {self.getColor(SiColor.INTERFACE_BG_B)};"
24 | f"border: 1px solid {self.getColor(SiColor.INTERFACE_BG_C)};"
25 | )
26 |
27 |
28 | self.content_ = SiPage(self.view_)
29 |
30 | # panel
31 | self.background_panel = SiLabel(self.view_)
32 | self.background_panel.setStyleSheet(
33 | "border-top-left-radius: 8px;"
34 | "border-top-right-radius: 8px;"
35 | f"background-color: {self.getColor(SiColor.INTERFACE_BG_C)}"
36 | )
37 | SiQuickEffect.applyDropShadowOn(self.background_panel, (0, 0, 0, 60), blur_radius=48)
38 |
39 | self.panel_ = SiDenseHContainer(self.view_)
40 | self.panel_.setAlignment(Qt.AlignCenter)
41 | self.panel_.setFixedHeight(80)
42 |
43 | # set self.view as center widget
44 | self.setCenterWidget(self.view_)
45 |
46 | def content(self):
47 | return self.content_
48 |
49 | def panel(self):
50 | return self.panel_
51 |
52 | def view(self):
53 | return self.view_
54 |
55 | def closeParentLayer(self):
56 | self.parent().closeLayer()
57 |
58 | def setSizeRatio(self, width_ratio, height_ratio):
59 | self.width_ratio = width_ratio
60 | self.height_ratio = height_ratio
61 |
62 | def getSizeFitParent(self):
63 | return int(self.parent().width() * self.width_ratio), int(self.parent().height() * self.height_ratio)
64 |
65 | def adjustSize(self):
66 | width_from_ratio = int(self.parent().width() * self.width_ratio)
67 | height_from_ratio = int(self.parent().height() * self.height_ratio)
68 | self.view_.resize(width_from_ratio, height_from_ratio)
69 |
70 | total_width, total_height = self.view_.width(), self.view_.height()
71 | self.resize(total_width, total_height) # to update position of center widget
72 | self.content_.resize(total_width, total_height - self.panel_.height())
73 | self.panel_.setGeometry(48, total_height - self.panel_.height(), total_width - 96, self.panel_.height())
74 |
75 | self.background_content.resize(total_width, total_height)
76 | self.background_panel.setGeometry(0, total_height - self.panel_.height(), total_width, self.panel_.height())
--------------------------------------------------------------------------------
/siui/components/page/page.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt
2 |
3 | from siui.components.widgets.container import SiDenseHContainer, SiDenseVContainer
4 | from siui.components.widgets.label import SiLabel
5 | from siui.components.widgets.scrollarea import SiScrollArea
6 | from siui.core import SiGlobal, GlobalFont
7 | from siui.core import Si
8 | from siui.gui import SiFont
9 |
10 |
11 | class SiPage(SiDenseVContainer):
12 | """ 页面类,实例化后作为 SiliconApplication 中的单个页面 """
13 | def __init__(self, *args, **kwargs):
14 | super().__init__(*args, **kwargs)
15 |
16 | self.setSpacing(0)
17 | self.setSiliconWidgetFlag(Si.EnableAnimationSignals)
18 |
19 | self.scroll_maximum_width = 10000 # 滚动区域宽度限制
20 | self.title_height = 0 # 标题引入的高度偏移,内容的高度要减去标题的高度
21 | self.padding = 0 # 左右空白区域的宽度
22 |
23 | # 滚动区域对齐方式
24 | self.scroll_alignment = Qt.AlignCenter
25 |
26 | # 滚动区域
27 | self.scroll_area = SiScrollArea(self)
28 | self.setAdjustWidgetsSize(True)
29 |
30 | # 添加到垂直容器
31 | self.addWidget(self.scroll_area)
32 |
33 | def setAttachment(self, widget):
34 | """ 设置子控件 """
35 | self.scroll_area.setAttachment(widget)
36 |
37 | def attachment(self):
38 | """ 获取子控件 """
39 | return self.scroll_area.attachment()
40 |
41 | def setScrollMaximumWidth(self, width: int):
42 | """
43 | 设置滚动区域的子控件的最大宽度
44 | :param width: 最大宽度
45 | """
46 | self.scroll_maximum_width = width
47 | self.resize(self.size())
48 |
49 | def setScrollAlignment(self, a0):
50 | """
51 | 设置滚动区域的对齐方式
52 | :param a0: Qt 枚举值
53 | """
54 | self.scroll_alignment = a0
55 | self.resize(self.size())
56 |
57 | def setPadding(self, padding):
58 | """
59 | 内容左右距离边框的距离
60 | :param padding: 像素数
61 | """
62 | self.padding = padding
63 | self.resize(self.size())
64 |
65 | def setTitle(self, title: str):
66 | """
67 | 设置页面标题
68 | :param title: 标题
69 | """
70 | # 套标题用的水平容器
71 | self.title_container = SiDenseHContainer(self)
72 | self.title_container.setSpacing(0)
73 | self.title_container.setFixedHeight(32)
74 | self.title_container.setAlignment(Qt.AlignCenter)
75 |
76 | # 标题
77 | self.title = SiLabel(self)
78 | self.title.setFont(SiFont.tokenized(GlobalFont.L_BOLD))
79 | self.title.setFixedHeight(32)
80 | self.title.setContentsMargins(64, 0, 0, 0)
81 | self.title.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
82 | self.title.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged)
83 |
84 | # 添加到水平容器
85 | self.title_container.addWidget(self.title)
86 |
87 | self.title.setText(title)
88 |
89 | # 添加到垂直容器
90 | self.addPlaceholder(32, index=0)
91 | self.addWidget(self.title_container, index=0)
92 | self.addPlaceholder(32, index=0)
93 |
94 | self.title_height = 96
95 |
96 | def reloadStyleSheet(self):
97 | super().reloadStyleSheet()
98 | self.title.setStyleSheet("color: {}".format(SiGlobal.siui.colors["TEXT_A"]))
99 |
100 | def resizeEvent(self, event):
101 | super().resizeEvent(event)
102 | size = event.size()
103 |
104 | self.scroll_area.resize(size.width(), size.height() - self.title_height)
105 | self.scroll_area.attachment().setFixedWidth(min(size.width() - self.padding * 2, self.scroll_maximum_width))
106 |
107 | # 处理对齐
108 | if (self.scroll_alignment & Qt.AlignHCenter) == Qt.AlignHCenter:
109 | scroll_widget_x = (size.width() - self.scroll_area.attachment().width())//2
110 | elif (self.scroll_alignment & Qt.AlignLeft) == Qt.AlignLeft:
111 | scroll_widget_x = self.padding
112 | elif (self.scroll_alignment & Qt.AlignRight) == Qt.AlignRight:
113 | scroll_widget_x = size.width() - self.scroll_area.attachment().width() - self.padding
114 | else:
115 | raise ValueError(f"Invalid alignment value: {self.scroll_alignment}")
116 |
117 | scroll_widget_y = self.scroll_area.attachment().y()
118 |
119 | self.scroll_area.attachment().move(scroll_widget_x, scroll_widget_y)
120 | self.scroll_area.animationGroup().fromToken("scroll").setTarget([scroll_widget_x, scroll_widget_y])
121 | self.scroll_area.animationGroup().fromToken("scroll").setCurrent([scroll_widget_x, scroll_widget_y])
122 |
--------------------------------------------------------------------------------
/siui/components/progress_bar/__init__.py:
--------------------------------------------------------------------------------
1 | from siui.components.progress_bar.progress_bar import *
--------------------------------------------------------------------------------
/siui/components/slider/__init__.py:
--------------------------------------------------------------------------------
1 | from siui.components.slider.slider import *
--------------------------------------------------------------------------------
/siui/components/spinbox/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/siui/components/spinbox/__init__.py
--------------------------------------------------------------------------------
/siui/components/spinbox/spinbox.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtGui import QDoubleValidator, QIntValidator
2 |
3 | from siui.components.widgets.button import SiSimpleButton
4 | from siui.components.widgets.line_edit import SiLineEdit
5 | from siui.core import SiGlobal
6 |
7 |
8 | class ABCSiSpinBox(SiLineEdit):
9 | def __init__(self, *args, **kwargs):
10 | super().__init__(*args, **kwargs)
11 | self.single_step_ = 1
12 | self.value_ = 0
13 | self.minimum_ = 0
14 | self.maximum_ = 99
15 |
16 | self.button_plus = SiSimpleButton(self)
17 | self.button_plus.resize(24, 24)
18 | self.button_plus.attachment().setSvgSize(12, 12)
19 | self.button_plus.attachment().load(SiGlobal.siui.iconpack.get("ic_fluent_chevron_up_regular"))
20 | self.button_plus.setRepetitiveClicking(True)
21 | self.button_plus.clicked.connect(self.stepForth)
22 |
23 | self.button_minus = SiSimpleButton(self)
24 | self.button_minus.resize(24, 24)
25 | self.button_minus.attachment().setSvgSize(12, 12)
26 | self.button_minus.attachment().load(SiGlobal.siui.iconpack.get("ic_fluent_chevron_down_regular"))
27 | self.button_minus.setRepetitiveClicking(True)
28 | self.button_minus.clicked.connect(self.stepBack)
29 |
30 | self.container().setSpacing(0)
31 | self.container().addPlaceholder(8, "right")
32 | self.container().addWidget(self.button_plus, "right")
33 | self.container().addPlaceholder(4, "right")
34 | self.container().addWidget(self.button_minus, "right")
35 |
36 | def singleStep(self):
37 | return self.single_step_
38 |
39 | def setSingleStep(self, step):
40 | self.single_step_ = step
41 |
42 | def minimum(self):
43 | return self.minimum_
44 |
45 | def setMinimum(self, minimum):
46 | self.minimum_ = minimum
47 |
48 | def maximum(self):
49 | return self.maximum_
50 |
51 | def setMaximum(self, maximum):
52 | self.maximum_ = maximum
53 |
54 | def value(self):
55 | return self.value_
56 |
57 | def setValue(self, value):
58 | self.value_ = min(self.maximum_, max(value, self.minimum_))
59 |
60 | def stepForth(self):
61 | self.setValue(self.value() + self.singleStep())
62 |
63 | def stepBack(self):
64 | self.setValue(self.value() - self.singleStep())
65 |
66 | def stepBy(self, step):
67 | self.setValue(self.value() + step)
68 |
69 |
70 | class SiIntSpinBox(ABCSiSpinBox):
71 | def __init__(self, *args, **kwargs):
72 | super().__init__(*args, **kwargs)
73 |
74 | self.lineEdit().setValidator(QIntValidator())
75 | self.lineEdit().setText(str(self.value()))
76 | self.lineEdit().editingFinished.connect(self.on_editing_finished)
77 |
78 | def on_editing_finished(self):
79 | value = int(self.lineEdit().text())
80 | self.setValue(value)
81 | if value < self.minimum() or value > self.maximum():
82 | try:
83 | SiGlobal.siui.windows["MAIN_WINDOW"].LayerRightMessageSidebar().send(
84 | title="输入值超出范围",
85 | text=f"限制输入值为介于 {self.minimum()} 到 {self.maximum()} 的整数\n"
86 | "已修改为最接近的值",
87 | msg_type=3,
88 | icon=SiGlobal.siui.iconpack.get("ic_fluent_warning_regular"),
89 | fold_after=2500,
90 | )
91 | except ValueError:
92 | pass
93 |
94 | def setValue(self, value):
95 | super().setValue(value)
96 | self.lineEdit().setText(str(self.value()))
97 |
98 |
99 | class SiDoubleSpinBox(ABCSiSpinBox):
100 | def __init__(self, *args, **kwargs):
101 | super().__init__(*args, **kwargs)
102 |
103 | self.setSingleStep(0.1)
104 |
105 | self.lineEdit().setValidator(QDoubleValidator())
106 | self.lineEdit().setText(str(self.value()))
107 | self.lineEdit().editingFinished.connect(self.on_editing_finished)
108 |
109 | def on_editing_finished(self):
110 | value = float(self.lineEdit().text())
111 | self.setValue(value)
112 | if value < self.minimum() or value > self.maximum():
113 | try:
114 | SiGlobal.siui.windows["MAIN_WINDOW"].LayerRightMessageSidebar().send(
115 | title="输入值超出范围",
116 | text=f"限制输入值为介于 {self.minimum()} 到 {self.maximum()} 的浮点数\n"
117 | "已修改为最接近的值",
118 | msg_type=3,
119 | icon=SiGlobal.siui.iconpack.get("ic_fluent_warning_regular"),
120 | fold_after=2500,
121 | )
122 | except ValueError:
123 | pass
124 |
125 | def setValue(self, value):
126 | # 重写以解决浮点数有效位溢出问题
127 | self.value_ = round(min(self.maximum_, max(value, self.minimum_)), 13) # 舍掉一些精度以追求计算准确
128 | self.lineEdit().setText(str(self.value()))
129 |
--------------------------------------------------------------------------------
/siui/components/titled_widget_group/__init__.py:
--------------------------------------------------------------------------------
1 | from siui.components.titled_widget_group.titled_widget_group import SiTitledWidgetGroup
--------------------------------------------------------------------------------
/siui/components/titled_widget_group/titled_widget_group.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt
2 |
3 | from siui.components.widgets.container import SiDenseVContainer
4 | from siui.components.widgets.label import SiLabel
5 | from siui.core import SiGlobal, GlobalFont
6 | from siui.core import Si
7 | from siui.gui import SiFont
8 |
9 |
10 | class GroupTitle(SiLabel):
11 | def __init__(self, *args, **kwargs):
12 | super().__init__(*args, **kwargs)
13 |
14 | self.setFixedHeight(26)
15 |
16 | # 标题文字
17 | self.title_label = SiLabel(self)
18 | self.title_label.setFont(SiFont.tokenized(GlobalFont.M_BOLD))
19 | self.title_label.setFixedHeight(26)
20 | self.title_label.setAlignment(Qt.AlignBottom)
21 | self.title_label.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged)
22 |
23 | # 标题高光,显示在文字下方
24 | self.title_highlight = SiLabel(self)
25 | self.title_highlight.lower()
26 | self.title_highlight.setFixedStyleSheet("border-radius: 4px")
27 |
28 | # 标题指示器,显示在文字左侧
29 | self.title_indicator = SiLabel(self)
30 | self.title_indicator.resize(5, 18)
31 | self.title_indicator.setFixedStyleSheet("border-radius: 2px")
32 |
33 | def reloadStyleSheet(self):
34 | super().reloadStyleSheet()
35 |
36 | self.setStyleSheet("background-color: transparent")
37 | self.title_label.setStyleSheet("color: {}".format(SiGlobal.siui.colors["TEXT_A"]))
38 | self.title_indicator.setStyleSheet("background-color: {}".format(SiGlobal.siui.colors["TITLE_INDICATOR"]))
39 | self.title_highlight.setStyleSheet("background-color: {}".format(SiGlobal.siui.colors["TITLE_HIGHLIGHT"]))
40 |
41 | def setText(self, text: str):
42 | self.title_label.setText(text)
43 | self.adjustSize()
44 |
45 | def adjustSize(self):
46 | self.resize(self.title_label.width() + 12 + 4, self.height())
47 |
48 | def resizeEvent(self, event):
49 | super().resizeEvent(event)
50 |
51 | self.title_indicator.move(0, 4)
52 | self.title_label.move(12, 0)
53 | self.title_highlight.setGeometry(12, 12, self.title_label.width() + 4, 13)
54 |
55 |
56 | class SiTitledWidgetGroup(SiDenseVContainer):
57 | def __init__(self, *args, **kwargs):
58 | super().__init__(*args, **kwargs)
59 |
60 | self.setAdjustWidgetsSize(True)
61 | self.setSpacing(8)
62 |
63 | def addTitle(self, title):
64 | """
65 | 添加新标题,这将创建一个标题组件并添加到自身中
66 | :param title: 标题文字
67 | """
68 | if len(self.widgets_top) > 0:
69 | self.addPlaceholder(16)
70 |
71 | new_title = GroupTitle(self)
72 | new_title.setText(title)
73 | self.addWidget(new_title)
74 |
75 | def addWidget(self, widget, side="top", index=10000):
76 | super().addWidget(widget, side, index)
77 | try:
78 | widget.resized.connect(self._on_child_resized)
79 | except: # noqa: E722
80 | pass
81 | # print(f"子控件 {widget} 似乎不具有正确形式的 resized 信号(pyqtSignal(list))")
82 |
83 | def _on_child_resized(self, _):
84 | self.adjustSize()
85 |
--------------------------------------------------------------------------------
/siui/components/tooltip/__init__.py:
--------------------------------------------------------------------------------
1 | from siui.components.tooltip.tooltip import ToolTipWindow
--------------------------------------------------------------------------------
/siui/components/widgets/__init__.py:
--------------------------------------------------------------------------------
1 | import siui.components.widgets.abstracts as abstarcts
2 | from siui.components.widgets.button import *
3 | from siui.components.widgets.container import *
4 | from siui.components.widgets.label import *
5 | from siui.components.widgets.line_edit import *
6 | from siui.components.widgets.scrollarea import *
7 |
--------------------------------------------------------------------------------
/siui/components/widgets/abstracts/__init__.py:
--------------------------------------------------------------------------------
1 |
2 | from siui.components.widgets.abstracts.button import *
3 | from siui.components.widgets.abstracts.label import *
4 | from siui.components.widgets.abstracts.line_edit import *
5 | from siui.components.widgets.abstracts.navigation_bar import *
6 | from siui.components.widgets.abstracts.widget import *
7 |
--------------------------------------------------------------------------------
/siui/components/widgets/abstracts/container.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import QSize
2 |
3 | from siui.components.widgets.abstracts.widget import SiWidget
4 |
5 |
6 | class SiSection:
7 | def __init__(self, width=0, height=0, alignment=None):
8 | self.width_ = width
9 | self.height_ = height
10 | self.alignment_ = alignment
11 |
12 | def setWidth(self, width):
13 | self.width_ = width
14 |
15 | def setHeight(self, height):
16 | self.height_ = height
17 |
18 | def setAlignment(self, alignment):
19 | self.alignment_ = alignment
20 |
21 | def width(self):
22 | return self.width_
23 |
24 | def height(self):
25 | return self.height_
26 |
27 | def size(self):
28 | return QSize(self.width_, self.height_)
29 |
30 | def alignment(self):
31 | return self.alignment_
32 |
33 | def __str__(self):
34 | text = f""
35 | return text
36 |
37 |
38 | class SiSectionTemplate:
39 | def __init__(self):
40 | self.sections_ = []
41 | self.spacing_ = 0
42 |
43 | def sections(self):
44 | return self.sections_
45 |
46 | def addSection(self, width=0, height=0, alignment=None):
47 | self.sections_.append(SiSection(width, height, alignment))
48 |
49 | def spacing(self):
50 | return self.spacing_
51 |
52 | def setSpacing(self, spacing: int):
53 | self.spacing_ = spacing
54 |
55 |
56 | class ABCSiDividedContainer(SiWidget):
57 | def __init__(self, *args, **kwargs):
58 | super().__init__(*args, **kwargs)
59 |
60 | self.sections_and_widgets = []
61 | self.spacing_ = 0
62 |
63 | def spacing(self):
64 | return self.spacing_
65 |
66 | def setSpacing(self, spacing: int):
67 | self.spacing_ = spacing
68 |
69 | def sections(self):
70 | return [a[0] for a in self.sections_and_widgets]
71 |
72 | def addSection(self, width=None, height=None, alignment=None):
73 | self.sections_and_widgets.append([SiSection(width, height, alignment), None])
74 |
75 | def setTemplate(self, template: SiSectionTemplate):
76 | self.setSpacing(template.spacing())
77 | for index, section in enumerate(template.sections()):
78 | if index < len(self.sections_and_widgets):
79 | self.sections_and_widgets[index][0] = section
80 | else:
81 | self.sections_and_widgets.append([section, None])
82 |
83 | def widgets(self):
84 | return [a[1] for a in self.sections_and_widgets]
85 |
86 | def addWidget(self, widget, index=None):
87 | if index is None:
88 | index = self.widgets().index(None)
89 |
90 | widget.setParent(self)
91 |
92 | if self.sections_and_widgets[index][1] is not None:
93 | self.sections_and_widgets[index][1].deleteLater()
94 | self.sections_and_widgets[index][1] = widget
95 |
--------------------------------------------------------------------------------
/siui/components/widgets/abstracts/line_edit.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt, pyqtSignal
2 | from PyQt5.QtWidgets import QLineEdit
3 |
4 | from siui.components.widgets.abstracts.widget import SiWidget
5 | from siui.components.widgets.container import SiDenseHContainer
6 | from siui.components.widgets.label import SiLabel
7 | from siui.core import SiColor, GlobalFont
8 | from siui.core import SiGlobal
9 | from siui.gui import SiFont
10 |
11 |
12 | class SiSimpleLineEdit(QLineEdit):
13 | onFocus = pyqtSignal(bool)
14 |
15 | def __init__(self, *args, **kwargs):
16 | super().__init__(*args, **kwargs)
17 |
18 | # 设置字体
19 | self.setFont(SiFont.tokenized(GlobalFont.S_NORMAL))
20 |
21 | def reloadStyleSheet(self):
22 | self.setStyleSheet(
23 | "QLineEdit {"
24 | " selection-background-color: #493F4E;"
25 | " background-color: transparent;"
26 | f" color: {self.parent().getColor(SiColor.TEXT_C)};"
27 | " border: 0px"
28 | "}"
29 | )
30 |
31 | def focusInEvent(self, event):
32 | super().focusInEvent(event)
33 | self.onFocus.emit(True)
34 |
35 | def focusOutEvent(self, event):
36 | super().focusOutEvent(event)
37 | self.onFocus.emit(False)
38 |
39 |
40 | class ABCSiLineEdit(SiWidget):
41 | def __init__(self, *args, **kwargs):
42 | super().__init__(*args, **kwargs)
43 |
44 | self.is_focus_in = False
45 | self.padding_ = 0
46 |
47 | self.container_ = SiDenseHContainer(self)
48 | self.container_.setAlignment(Qt.AlignVCenter)
49 |
50 | self.outfit_label_top = SiLabel(self)
51 | self.outfit_label_top.lower()
52 | self.outfit_label_top.setFixedStyleSheet(
53 | "border-top-left-radius: 4px;"
54 | "border-top-right-radius: 4px;"
55 | "border-bottom-left-radius: 2px;"
56 | "border-bottom-right-radius: 2px;"
57 | )
58 |
59 | self.outfit_label_bottom = SiLabel(self)
60 | self.outfit_label_bottom.stackUnder(self.outfit_label_top)
61 | self.outfit_label_bottom.setFixedStyleSheet("border-radius: 4px")
62 |
63 | def container(self):
64 | return self.container_
65 |
66 | def setPadding(self, padding):
67 | self.padding_ = padding
68 | self.resize(self.size())
69 |
70 | def padding(self):
71 | return self.padding_
72 |
73 | def setFocusState(self, state):
74 | self.is_focus_in = state
75 | self.on_focus_changed(self.is_focus_in)
76 |
77 | def focusState(self):
78 | return self.is_focus_in
79 |
80 | def on_focus_changed(self, is_on):
81 | w, h = self.size().width(), self.size().height()
82 | if is_on:
83 | self.outfit_label_top.resize(w, h - 2)
84 | else:
85 | self.outfit_label_top.resize(w, h - 1)
86 |
87 | def reloadStyleSheet(self):
88 | super().reloadStyleSheet()
89 |
90 | self.outfit_label_top.setStyleSheet(
91 | f"background-color: {self.getColor(SiColor.INTERFACE_BG_B)};"
92 | f"border-left: 1px solid {self.getColor(SiColor.INTERFACE_BG_D)};"
93 | f"border-right: 1px solid {self.getColor(SiColor.INTERFACE_BG_D)};"
94 | f"border-top: 1px solid {self.getColor(SiColor.INTERFACE_BG_D)};"
95 | )
96 | self.outfit_label_bottom.setStyleSheet(
97 | "background-color: qlineargradient(x1:0, y1:0, x2:1, y2:1,"
98 | f" stop:0 {self.getColor(SiColor.THEME_TRANSITION_A)},"
99 | f" stop:1 {self.getColor(SiColor.THEME_TRANSITION_B)}"
100 | ")"
101 | )
102 |
103 | def resizeEvent(self, event):
104 | super().resizeEvent(event)
105 | self.container_.resize(event.size())
106 | self.outfit_label_bottom.resize(event.size())
107 | self.outfit_label_top.setGeometry(
108 | self.padding_, 0, event.size().width() - 2 * self.padding_, event.size().height() - 1)
109 |
--------------------------------------------------------------------------------
/siui/components/widgets/abstracts/navigation_bar.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import pyqtSignal
2 |
3 | from siui.components.widgets.abstracts.widget import SiWidget
4 |
5 |
6 | class ABCSiNavigationBar(SiWidget):
7 | """ 抽象导航栏 """
8 | indexChanged = pyqtSignal(int)
9 |
10 | def __init__(self, *args, **kwargs):
11 | super().__init__(*args, **kwargs)
12 |
13 | # 当前索引
14 | self.current_index_ = -1
15 |
16 | # 最大索引,需要最先设置
17 | self.maximum_index_ = -1
18 |
19 | def setCurrentIndex(self, index):
20 | """ 设置当前索引 """
21 | self.current_index_ = index % (self.maximumIndex() + 1)
22 | self.indexChanged.emit(self.currentIndex())
23 |
24 | def currentIndex(self):
25 | """ 获取当前索引 """
26 | return self.current_index_
27 |
28 | def setMaximumIndex(self, max_index):
29 | """ 设置最大的索引,超过最大索引的索引将会被取余数 """
30 | if max_index < self.maximumIndex():
31 | self.maximum_index_ = max_index
32 | self.setCurrentIndex(self.currentIndex()) # 如果最大索引变小,这样可以防止其超过界限
33 | else:
34 | self.maximum_index_ = max_index
35 |
36 | def maximumIndex(self):
37 | """ 获取最大的索引 """
38 | return self.maximum_index_
39 |
40 | def shift(self, step: int):
41 | """
42 | 将当前索引加 step
43 | :param step: 步长
44 | """
45 | self.setCurrentIndex(self.currentIndex() + step)
46 |
--------------------------------------------------------------------------------
/siui/components/widgets/expands.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt
2 | from PyQt5.QtWidgets import QWidget
3 |
4 | from siui.components import SiDenseHContainer, SiIconLabel, SiLabel, SiSvgLabel, SiWidget
5 | from siui.core import SiColor, SiExpAccelerateAnimation, SiGlobal
6 |
7 |
8 | class SiHExpandWidget(SiWidget):
9 | def __init__(self, *args, **kwargs):
10 | super().__init__(*args, **kwargs)
11 |
12 | self.attachment_ = SiWidget(self)
13 |
14 | self.expand_animation = SiExpAccelerateAnimation(self)
15 | self.expand_animation.setAccelerateFunction(lambda x: (x / 10) ** 3)
16 | self.expand_animation.setFactor(1/4)
17 | self.expand_animation.setBias(0.01)
18 | self.expand_animation.setCurrent(1)
19 | self.expand_animation.setTarget(1)
20 | self.expand_animation.ticked.connect(self.on_ani_ticked)
21 |
22 | self.animationGroup().addMember(self.expand_animation, "expand")
23 |
24 | def attachment(self):
25 | return self.attachment_
26 |
27 | def setAttachment(self, att: QWidget):
28 | self.attachment_.deleteLater()
29 | self.attachment_ = att
30 | att.setParent(self)
31 |
32 | def expand(self, percent):
33 | self.expand_animation.stop()
34 | self.expand_animation.setTarget(percent)
35 | self.expand_animation.setCurrent(percent)
36 |
37 | def expandTo(self, percent):
38 | self.expand_animation.setTarget(percent)
39 | self.expand_animation.try_to_start()
40 |
41 | def on_ani_ticked(self, value):
42 | value = float(value) # 绑定控件半边的长度占整个控件半侧的百分比
43 | one_side_width = int(self.width() / 2 * value)
44 | x = self.width() // 2 - one_side_width
45 | width = one_side_width * 2
46 | self.attachment_.setGeometry(x, 0, width, self.height())
47 |
48 | def resizeEvent(self, event):
49 | super().resizeEvent(event)
50 | self.on_ani_ticked(self.expand_animation.current()) # 强制刷新绑定控件大小
51 |
52 |
53 | class SiVExpandWidget(SiWidget):
54 | def __init__(self, *args, **kwargs):
55 | super().__init__(*args, **kwargs)
56 |
57 | self.attachment_ = SiWidget(self)
58 |
59 | self.expand_animation = SiExpAccelerateAnimation(self)
60 | self.expand_animation.setAccelerateFunction(lambda x: (x / 10) ** 3)
61 | self.expand_animation.setFactor(1/4)
62 | self.expand_animation.setBias(0.01)
63 | self.expand_animation.setCurrent(1)
64 | self.expand_animation.setTarget(1)
65 | self.expand_animation.ticked.connect(self.on_ani_ticked)
66 |
67 | self.animationGroup().addMember(self.expand_animation, "expand")
68 |
69 | def attachment(self):
70 | return self.attachment_
71 |
72 | def setAttachment(self, att: QWidget):
73 | self.attachment_.deleteLater()
74 | self.attachment_ = att
75 | att.setParent(self)
76 |
77 | def expand(self, percent):
78 | self.expand_animation.stop()
79 | self.expand_animation.setTarget(percent)
80 | self.expand_animation.setCurrent(percent)
81 |
82 | def expandTo(self, percent):
83 | self.expand_animation.setTarget(percent)
84 | self.expand_animation.try_to_start()
85 |
86 | def on_ani_ticked(self, value):
87 | value = float(value) # 绑定控件半边的长度占整个控件半侧的百分比
88 | one_side_height = int(self.height() / 2 * value)
89 | y = self.height() // 2 - one_side_height
90 | height = one_side_height * 2
91 | self.attachment_.setGeometry(0, y, self.width(), height)
92 |
93 | def resizeEvent(self, event):
94 | super().resizeEvent(event)
95 | self.on_ani_ticked(self.expand_animation.current()) # 强制刷新绑定控件大小
96 |
97 |
98 | class SiHoverExpandWidget(SiVExpandWidget):
99 | def __init__(self, *args, **kwargs):
100 | super().__init__(*args, **kwargs)
101 |
102 | self.h_expand_widget = SiHExpandWidget(self)
103 |
104 | self.frame = SiLabel(self)
105 | self.frame.setFixedStyleSheet("border-radius: 4px")
106 | self.frame.setColor(SiColor.mix(self.getColor(SiColor.INTERFACE_BG_D), self.getColor(SiColor.SIDE_MSG_THEME_SUCCESS)))
107 |
108 | self.container = SiDenseHContainer(self.frame)
109 | self.container.setFixedHeight(32)
110 |
111 | self.icon = SiSvgLabel(self)
112 | self.icon.load(SiGlobal.siui.iconpack.get("ic_fluent_arrow_sync_filled"))
113 | self.icon.resize(32, 32)
114 |
115 | self.label = SiLabel(self)
116 | self.label.setTextColor(self.getColor(SiColor.TEXT_B))
117 | self.label.setAlignment(Qt.AlignCenter)
118 | self.label.setText("重载成功")
119 | self.label.setFixedHeight(32)
120 | self.label.adjustSize()
121 |
122 | self.container.setSpacing(0)
123 | self.container.addWidget(self.icon)
124 | self.container.addWidget(self.label)
125 |
126 | self.frame.adjustSize()
127 |
128 | self.h_expand_widget.setAttachment(self.frame)
129 | self.setAttachment(self.h_expand_widget)
130 |
131 | def enterEvent(self, a0):
132 | super().enterEvent(a0)
133 | self.expandTo(1)
134 | self.h_expand_widget.expandTo(1)
135 | # self.frame.setOpacityTo(1)
136 |
137 | def leaveEvent(self, a0):
138 | super().leaveEvent(a0)
139 | self.expandTo(1)
140 | self.h_expand_widget.expandTo(32 / self.width())
141 | # self.frame.setOpacityTo(0.1)
142 |
--------------------------------------------------------------------------------
/siui/components/widgets/line_edit.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt
2 | from PyQt5.QtWidgets import QLineEdit
3 |
4 | from siui.components.widgets import SiLabel, SiWidget
5 | from siui.components.widgets.abstracts import ABCSiLineEdit, SiSimpleLineEdit
6 | from siui.components.widgets.button import SiSimpleButton
7 | from siui.core import SiGlobal, SiColor, SiExpAnimation
8 |
9 |
10 | class SiLineEdit(ABCSiLineEdit):
11 | def __init__(self, *args, **kwargs):
12 | super().__init__(*args, **kwargs)
13 |
14 | self.line_edit = SiSimpleLineEdit(self)
15 | self.line_edit.setTextMargins(12, 0, 12, 1)
16 | self.line_edit.setAlignment(Qt.AlignVCenter | Qt.AlignLeft)
17 | self.line_edit.onFocus.connect(self.on_focus_changed)
18 | self.line_edit.returnPressed.connect(self.line_edit.clearFocus) # 按下回车,移出焦点
19 | self.container().addWidget(self.line_edit)
20 |
21 | def adjustLineEditSize(self):
22 | preferred_width = self.container().width() - self.container().getUsedSpace("right")
23 | self.line_edit.resize(preferred_width, self.line_edit.height())
24 |
25 | def lineEdit(self):
26 | return self.line_edit
27 |
28 | def resizeEvent(self, event):
29 | super().resizeEvent(event)
30 | self.adjustLineEditSize()
31 |
32 |
33 | class SiLineEditWithDeletionButton(SiLineEdit):
34 | def __init__(self, *args, **kwargs):
35 | super().__init__(*args, **kwargs)
36 |
37 | self.deletion_button = SiSimpleButton(self)
38 | self.deletion_button.resize(24, 24)
39 | self.deletion_button.attachment().setSvgSize(16, 16)
40 | self.deletion_button.attachment().load(SiGlobal.siui.iconpack.get("ic_fluent_delete_regular"))
41 | self.deletion_button.clicked.connect(self.clear_text)
42 | self.container().setSpacing(0)
43 | self.container().addPlaceholder(8, "right")
44 | self.container().addWidget(self.deletion_button, "right")
45 |
46 | def clear_text(self):
47 | self.lineEdit().setText("")
48 |
49 |
50 | class SiLineEditWithItemName(SiWidget):
51 | def __init__(self, *args, **kwargs):
52 | super().__init__(*args, **kwargs)
53 |
54 | self.name_spacing = 128
55 |
56 | self.base_panel = SiLabel(self)
57 | self.base_panel.setFixedStyleSheet("border-radius: 6px")
58 | self.base_panel.animation_color.setBias(1)
59 | self.base_panel.animation_color.setFactor(1/32)
60 |
61 | self.edit_panel = SiLabel(self)
62 | self.edit_panel.setFixedStyleSheet("border-radius: 6px")
63 |
64 | self.name_label = SiLabel(self)
65 | self.name_label.setContentsMargins(16, 0, 16, 0)
66 | self.name_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
67 |
68 | self.line_edit = SiSimpleLineEdit(self.edit_panel)
69 | self.line_edit.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
70 | self.line_edit.setTextMargins(16, 0, 16, 0)
71 | self.line_edit.textEdited.connect(self.flash_on_edited)
72 |
73 | def reloadStyleSheet(self):
74 | super().reloadStyleSheet()
75 | c = self.getColor(SiColor.INTERFACE_BG_C)
76 | b = self.getColor(SiColor.INTERFACE_BG_B)
77 | a = self.getColor(SiColor.INTERFACE_BG_A)
78 |
79 | self.base_panel.setColor(SiColor.mix(c, b, 0.3))
80 | self.edit_panel.setColor(SiColor.mix(b, a, 0.5))
81 | self.name_label.setTextColor(self.getColor(SiColor.TEXT_D))
82 |
83 | def flash_on_edited(self):
84 | c = self.getColor(SiColor.INTERFACE_BG_C)
85 | b = self.getColor(SiColor.INTERFACE_BG_B)
86 | self.base_panel.setColor(self.getColor(SiColor.INTERFACE_BG_E))
87 | self.base_panel.setColorTo(SiColor.mix(c, b, 0.3))
88 |
89 | def setName(self, name: str):
90 | self.name_label.setText(name)
91 |
92 | def lineEdit(self):
93 | return self.line_edit
94 |
95 | def setNameSpacing(self, spacing):
96 | self.name_spacing = spacing
97 | self.resize(self.size())
98 |
99 | def resizeEvent(self, event):
100 | super().resizeEvent(event)
101 | self.base_panel.resize(event.size())
102 | self.edit_panel.setGeometry(
103 | self.name_spacing, 0, event.size().width() - self.name_spacing, event.size().height())
104 | self.name_label.resize(self.name_spacing, event.size().height())
105 | self.line_edit.resize(self.edit_panel.size())
106 |
--------------------------------------------------------------------------------
/siui/components/widgets/table.py:
--------------------------------------------------------------------------------
1 | from siui.components import SiLabel, SiMasonryContainer, SiScrollArea, SiWidget
2 | from siui.components.widgets.abstracts.table import ABCSiTabelManager, ABCSiTable, SiRow
3 | from siui.core import GlobalFont, Si, SiColor
4 | from siui.gui import SiFont
5 |
6 |
7 | class SiTableValueManagerLabels(ABCSiTabelManager):
8 | def _value_read_parser(self, row_index, col_index):
9 | return self.parent().getRowWidget(row_index)[col_index].text()
10 |
11 | def _value_write_parser(self, row_index, col_index, value):
12 | self.parent().getRowWidget(row_index)[col_index].setText(value)
13 |
14 | def _widget_creator(self, col_index):
15 | label = SiLabel(self.parent())
16 | label.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged)
17 | label.setFixedStyleSheet("color: #e5e5e5")
18 | return label
19 |
20 | def on_header_created(self, header: SiRow):
21 | for name in self.parent().column_names:
22 | new_label = SiLabel(self.parent())
23 | new_label.setFont(SiFont.tokenized(GlobalFont.S_BOLD))
24 | new_label.setTextColor(self.parent().getColor(SiColor.TEXT_B))
25 | new_label.setText(name)
26 | new_label.adjustSize()
27 | header.container().addWidget(new_label)
28 |
29 | header.container().arrangeWidgets()
30 |
31 |
32 | class SiTableView(ABCSiTable):
33 | def __init__(self, *args, **kwargs):
34 | super().__init__(*args, **kwargs)
35 |
36 | self.padding = 20
37 |
38 | self.panel = SiLabel(self)
39 | self.panel.setFixedStyleSheet("border-radius: 8px")
40 |
41 | self.header_panel = SiLabel(self)
42 | self.header_panel.setFixedStyleSheet("border-top-left-radius: 8px; border-top-right-radius: 8px")
43 |
44 | self.container_ = SiMasonryContainer(self)
45 | self.container_.setSpacing(vertical=0)
46 | self.container_.setColumns(1)
47 |
48 | self.scroll_area = SiScrollArea(self)
49 | self.scroll_area.setAttachment(self.container_)
50 |
51 | self.setManager(SiTableValueManagerLabels(self))
52 | self.header_row = SiRow(self)
53 |
54 | self.indicator_frame = SiWidget(self)
55 | self.indicator_frame.setFixedHeight(6)
56 | self.indicator_frame.move(8, 44)
57 | self.indicator_frame.hide()
58 |
59 | self.indicator_track = SiLabel(self.indicator_frame)
60 | self.indicator_track.setFixedStyleSheet("border-radius: 1px")
61 | self.indicator_track.move(0, 2)
62 |
63 | def addRow(self, widgets: list = None, data: list = None):
64 | super().addRow(widgets, data)
65 |
66 | if len(self.rows_) % 2 == 0:
67 | color = self.getColor(SiColor.INTERFACE_BG_C)
68 | else:
69 | color = self.getColor(SiColor.INTERFACE_BG_B)
70 |
71 | self.rows_[-1].setFixedStyleSheet("border-radius: 6px")
72 | self.rows_[-1].setColor(color)
73 | self.rows_[-1].resize(self.width() - self.padding * 2, 40)
74 | self.container().arrangeWidgets()
75 |
76 | def addColumn(self,
77 | name: str,
78 | width: int = None,
79 | height: int = None,
80 | alignment=None):
81 | super().addColumn(name, width, height, alignment)
82 | self._load_header()
83 |
84 | def _load_header(self):
85 | self.header_row.deleteLater()
86 | self.header_row = SiRow(self)
87 | self.header_row.container().setTemplate(self.sectionTemplate())
88 | self.header_row.setGeometry(self.padding, 4, self.width() - self.padding * 2, 40)
89 | self.manager().on_header_created(self.header_row)
90 |
91 | def reloadStyleSheet(self):
92 | super().reloadStyleSheet()
93 |
94 | self.panel.setStyleSheet(
95 | f"border: 1px solid {self.getColor(SiColor.INTERFACE_BG_D)};"
96 | f"background-color: {self.getColor(SiColor.INTERFACE_BG_B)};"
97 | )
98 |
99 | self.header_panel.setStyleSheet(
100 | f"background-color: {self.getColor(SiColor.INTERFACE_BG_D)};"
101 | )
102 |
103 | self.indicator_track.setStyleSheet(
104 | f"background-color: {self.getColor(SiColor.THEME)}"
105 | )
106 |
107 | def resizeEvent(self, event):
108 | super().resizeEvent(event)
109 | self.panel.resize(event.size())
110 | self.header_panel.resize(event.size().width(), 48)
111 | self.header_row.setGeometry(self.padding, 4, event.size().width() - self.padding * 2, 40)
112 | self.indicator_frame.resize(event.size().width() - self.indicator_frame.x() * 2, 6)
113 | self.indicator_track.resize(self.indicator_frame.width(), 3)
114 |
115 | self.scroll_area.setGeometry(self.padding, 48, event.size().width() - self.padding, event.size().height() - 48 - 1)
116 | self.container().setGeometry(0, 0, event.size().width() - self.padding * 2, self.container().height())
117 | for row in self.rows():
118 | row.resize(event.size().width() - self.padding * 2, 40)
119 | self.container().arrangeWidgets()
120 |
--------------------------------------------------------------------------------
/siui/components/widgets/timeline.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt, QSize
2 |
3 | from siui.components import SiLabel, SiMasonryContainer, SiSvgLabel, SiWidget
4 | from siui.core import SiColor, SiGlobal
5 | from siui.gui import SiFont
6 |
7 |
8 | class SiTimeLineItem(SiWidget):
9 | def __init__(self, *args, **kwargs):
10 | super().__init__(*args, **kwargs)
11 |
12 | self.icon = SiSvgLabel(self)
13 | self.icon.setSvgSize(24, 24)
14 | self.icon.setFixedSize(32, 32)
15 | self.icon.move(16, 0)
16 |
17 | self.anchor = SiLabel(self)
18 | self.anchor.setFixedSize(24, 24)
19 | self.anchor.setFixedStyleSheet("border-radius: 12px")
20 | self.anchor.setStyleSheet(
21 | f"border: 4px solid {self.getColor(SiColor.INTERFACE_BG_C)};"
22 | f"background-color: {self.getColor(SiColor.INTERFACE_BG_E)};"
23 | )
24 | self.anchor.move(64 + 4, 4)
25 |
26 | self.anchor_dot = SiLabel(self.anchor)
27 | self.anchor_dot.setFixedSize(8, 8)
28 | self.anchor_dot.setFixedStyleSheet("border-radius: 4px")
29 | self.anchor_dot.move(8, 8)
30 | self.anchor_dot.setStyleSheet(
31 | f"background-color: {self.getColor(SiColor.INTERFACE_BG_C)};"
32 | )
33 |
34 | self.title = SiLabel(self)
35 | self.title.setFont(SiFont.getFont(size=12))
36 | self.title.setTextColor(self.getColor(SiColor.TEXT_D))
37 | self.title.setAlignment(Qt.AlignLeft)
38 | self.title.setContentsMargins(0, 8, 0, 2)
39 | self.title.move(112, 0)
40 | self.title.adjustSize()
41 |
42 | self.description = SiLabel(self)
43 | self.description.setTextColor(self.getColor(SiColor.TEXT_B))
44 | self.description.setAlignment(Qt.AlignLeft | Qt.AlignTop)
45 | self.description.move(112, self.title.height())
46 | self.description.adjustSize()
47 |
48 | def setContent(self, title, description):
49 | self.title.setText(title)
50 | self.title.adjustSize()
51 | self.description.setText(description)
52 | self.description.adjustSize()
53 |
54 | def setIconHint(self, text):
55 | self.icon.setHint(text)
56 |
57 | def setThemeColor(self, code, background_color=None):
58 | background_color = self.getColor(SiColor.INTERFACE_BG_C) if background_color is None else background_color
59 | self.anchor.setStyleSheet(
60 | f"border: 4px solid {background_color};"
61 | f"background-color: {code};"
62 | )
63 | self.anchor_dot.setStyleSheet(
64 | f"background-color: {background_color};"
65 | )
66 |
67 | def setIcon(self, path_or_data):
68 | self.icon.load(path_or_data)
69 |
70 | def sizeHint(self):
71 | return QSize(self.width(), max(self.title.height() + self.description.height(), 64))
72 |
73 | def resizeEvent(self, event):
74 | super().resizeEvent(event)
75 |
76 | self.title.resize(event.size().width() - 112, self.title.height())
77 | self.description.resize(event.size().width() - 112, self.description.height())
78 | self.description.move(112, self.title.height())
79 |
80 |
81 | class SiTimeLine(SiMasonryContainer):
82 | def __init__(self, *args, **kwargs):
83 | super().__init__(*args, **kwargs)
84 |
85 | self.setColumns(1)
86 | self.setColumnWidth(500)
87 |
88 | self.track = SiLabel(self)
89 | self.track.setFixedStyleSheet("border-radius: 2px")
90 | self.track.setColor(self.getColor(SiColor.INTERFACE_BG_E))
91 | self.track.setFixedWidth(4)
92 | self.track.resize(4, 100)
93 | self.track.move(14 + 64, 0)
94 |
95 | self.setMinimumWidth(500)
96 |
97 | def addWidget(self, widget, arrange=True, ani=True):
98 | super().addWidget(widget, arrange, ani)
99 | widget.resize(self.width(), widget.sizeHint().height())
100 |
101 | def resizeEvent(self, event):
102 | super().resizeEvent(event)
103 |
104 | for item in self.widgets():
105 | item.resize(event.size().width(), item.height())
106 |
107 | self.track.resize(4, event.size().height())
108 |
--------------------------------------------------------------------------------
/siui/core/__init__.py:
--------------------------------------------------------------------------------
1 | from .alignment import SiQuickAlignmentManager
2 | from .animation import (
3 | ABCSiAnimation,
4 | Curve,
5 | SiAnimationGroup,
6 | SiCounterAnimation,
7 | SiExpAccelerateAnimation,
8 | SiExpAnimation,
9 | SiSqrExpAnimation,
10 | )
11 | from .color import SiColor
12 | from .effect import SiQuickEffect
13 | from .enumrates import Si
14 | from .globals import NewGlobal, SiGlobal, hideToolTip, isToolTipInsideOf, isTooltipShown, showToolTip, updateToolTip
15 | from .painter import createPainter as createPainter
16 | from .token import FontStyle as FontStyle
17 | from .token import GlobalFont as GlobalFont
18 | from .token import GlobalFontSize as GlobalFontSize
19 | from .token import GlobalFontWeight as GlobalFontWeight
20 |
21 | __all__ = (
22 | "SiQuickAlignmentManager",
23 | "ABCSiAnimation",
24 | "Curve",
25 | "SiAnimationGroup",
26 | "SiCounterAnimation",
27 | "SiExpAccelerateAnimation",
28 | "SiExpAnimation",
29 | "SiSqrExpAnimation",
30 | "SiColor",
31 | "SiQuickEffect",
32 | "Si",
33 | "NewGlobal",
34 | "SiGlobal",
35 | "FontStyle",
36 | "GlobalFont",
37 | "GlobalFontSize",
38 | "GlobalFontWeight",
39 | "hideToolTip",
40 | "showToolTip",
41 | "updateToolTip",
42 | "isTooltipShown",
43 | "isToolTipInsideOf",
44 | )
45 |
--------------------------------------------------------------------------------
/siui/core/alignment.py:
--------------------------------------------------------------------------------
1 |
2 | from PyQt5.QtCore import QPoint, QSize, Qt
3 |
4 |
5 | class SiQuickAlignmentManager:
6 | @staticmethod
7 | def toPos(container_size: QSize,
8 | widget_size: QSize,
9 | flag):
10 | if (flag & Qt.AlignLeft) == Qt.AlignLeft:
11 | x = 0
12 | elif (flag & Qt.AlignHCenter) == Qt.AlignHCenter:
13 | x = (container_size.width() - widget_size.width()) // 2
14 | elif (flag & Qt.AlignRight) == Qt.AlignRight:
15 | x = container_size.width() - widget_size.width()
16 | else:
17 | x = 0
18 |
19 | if (flag & Qt.AlignTop) == Qt.AlignTop:
20 | y = 0
21 | elif (flag & Qt.AlignVCenter) == Qt.AlignVCenter:
22 | y = (container_size.height() - widget_size.height()) // 2
23 | elif (flag & Qt.AlignBottom) == Qt.AlignBottom:
24 | y = container_size.height() - widget_size.height()
25 | else:
26 | y = 0
27 |
28 | return QPoint(x, y)
29 |
--------------------------------------------------------------------------------
/siui/core/effect.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple, Union
2 |
3 | from PyQt5.QtGui import QColor
4 | from PyQt5.QtWidgets import QGraphicsDropShadowEffect, QGraphicsOpacityEffect, QWidget
5 |
6 |
7 | class SiQuickEffect:
8 | @staticmethod
9 | def applyDropShadowOn(widget: QWidget,
10 | color: Union[Tuple[int, int, int, int], None],
11 | offset: Union[Tuple[int, int], None] = None,
12 | blur_radius: int = 16):
13 | if color is None:
14 | color = (0, 0, 0, 255)
15 | if offset is None:
16 | offset = (0, 0)
17 |
18 | shadow = QGraphicsDropShadowEffect(widget)
19 | shadow.setColor(QColor(*color))
20 | shadow.setOffset(*offset)
21 | shadow.setBlurRadius(blur_radius)
22 | widget.setGraphicsEffect(shadow)
23 |
24 | @staticmethod
25 | def applyOpacityOn(widget: QWidget,
26 | opacity: float):
27 | opacity_effect = QGraphicsOpacityEffect()
28 | opacity_effect.setOpacity(opacity)
29 | widget.setGraphicsEffect(opacity_effect)
30 |
--------------------------------------------------------------------------------
/siui/core/enumrates.py:
--------------------------------------------------------------------------------
1 | from enum import Enum, auto
2 |
3 |
4 | class Si(Enum):
5 | # the namespace of SiliconUI
6 | # Flags for SiWidget
7 | FlashOnHintUpdated = auto() # 在工具提示被重新设置时,使工具提示闪烁
8 | InstantMove = auto() # 是否立即移动而不运行动画
9 | InstantResize = auto() # 是否立即重设大小而不运行动画
10 | InstantSetOpacity = auto() # 是否立即重设透明度而不运行动画
11 | HasMoveLimits = auto() # 是否有移动限定区域
12 | AdjustSizeOnTextChanged = auto() # 是否在setText被调用时自动调整空间大小
13 | EnableAnimationSignals = auto() # 是否启用moved,resized,opacityChanged信号
14 | DeleteOnHidden = auto() # 下一次被隐藏时,运行 deleteLater()
15 | DeleteCenterWidgetOnCenterWidgetHidden = auto() # 中心控件下一次被隐藏时,运行 centerWidget().deleteLater()
16 |
--------------------------------------------------------------------------------
/siui/core/function/__init__.py:
--------------------------------------------------------------------------------
1 | from siui.core.function.chain import SiFunctionChain, chain_trigger, CalcLater # noqa: I001, F401
2 |
--------------------------------------------------------------------------------
/siui/core/globals.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | from PyQt5.QtWidgets import QWidget
4 |
5 | from siui.core import SiColor
6 | from siui.gui.color_group import DarkColorGroup
7 | from siui.gui.icons.parser import GlobalIconPack
8 |
9 |
10 | class SiliconUIGlobal:
11 | """
12 | SiliconUI 内部使用的全局数据\n
13 | 如果你也需要使用全局数据,可以将你的类添加到 SiGlobal 的一个属性
14 | """
15 | # 窗口字典,储存窗口对象
16 | windows = {}
17 |
18 | # 颜色字典,存储全部动态设置的颜色
19 | # 值为 RRGGBB 或 AARRGGBB 色号
20 | colors = DarkColorGroup()
21 |
22 | # 图标字典,储存所有 SVG 类型的图标数据
23 | # 值为 SVG信息的 bytes
24 | icons = {}
25 | iconpack = GlobalIconPack()
26 | iconpack.setDefaultColor("#D1CBD4")
27 |
28 | # 样式表字典,储存所有动态样式表
29 | # 值为字符串
30 | qss = {}
31 |
32 | # 字体字典,储存所有字体
33 | # 值为 QFont 类型的字体
34 |
35 | def loadWindows(self, dictionary):
36 | SiliconUIGlobal.windows.update(dictionary)
37 |
38 | def loadColors(self, dictionary):
39 | SiliconUIGlobal.colors.update(dictionary)
40 |
41 | def loadIcons(self, dictionary):
42 | SiliconUIGlobal.icons.update(dictionary)
43 |
44 | def loadQSS(self, dictionary):
45 | SiliconUIGlobal.qss.update(dictionary)
46 |
47 | def loadFonts(self, dictionary):
48 | SiliconUIGlobal.fonts.update(dictionary)
49 |
50 | def reloadAllWindowsStyleSheet(self):
51 | """
52 | 调用各个窗口下的reloadStyleSheet方法并递归,重载所有窗口下所有控件的样式表
53 | """
54 | for window in self.windows.values():
55 | try:
56 | window.reloadStyleSheet()
57 | except AttributeError:
58 | pass
59 | self._reloadWidgetStyleSheet(window)
60 |
61 | def reloadStyleSheetRecursively(self, widget):
62 | """ run reloadStyleSheet() for all children of this widget """
63 | try:
64 | widget.reloadStyleSheet()
65 | except AttributeError:
66 | pass
67 | self._reloadWidgetStyleSheet(widget)
68 |
69 | def _reloadWidgetStyleSheet(self, widget):
70 | for child in widget.children():
71 | self._reloadWidgetStyleSheet(child)
72 | try:
73 | child.reloadStyleSheet()
74 | except AttributeError:
75 | pass
76 | return
77 |
78 |
79 | class SiGlobal:
80 | """
81 | 全局数据\n
82 | 在 siui 模块被第一次导入时初始化 .siui 下的变量
83 | """
84 | siui = SiliconUIGlobal()
85 |
86 |
87 | class NewGlobal:
88 | """
89 | 新全局数据
90 | """
91 | create_time = time.time()
92 |
93 |
94 | def toolTipWindow() -> QWidget:
95 | return SiGlobal.siui.windows.get("TOOL_TIP")
96 |
97 |
98 | def raiseToolTipWindow():
99 | window = toolTipWindow()
100 | if window is not None:
101 | window.raise_()
102 |
103 |
104 | def showToolTip(widget, flash: bool = True) -> None:
105 | """ Show tool tip of specified widget """
106 | window = toolTipWindow()
107 | if window is None:
108 | return
109 | if widget.toolTip() == "":
110 | return
111 | window.setText(widget.toolTip(), flash=flash)
112 | window.setNowInsideOf(widget)
113 | window.show_()
114 |
115 |
116 | def hideToolTip(widget) -> None:
117 | window = toolTipWindow()
118 | if window is None:
119 | return
120 | window.setNowInsideOf(None)
121 | window.hide_()
122 |
123 |
124 | def updateToolTip(widget, flash: bool = True) -> None:
125 | window = toolTipWindow()
126 | if window is None:
127 | return
128 | if widget.toolTip() == "":
129 | return
130 | window.setText(widget.toolTip(), flash=flash)
131 |
132 |
133 | def isTooltipShown() -> bool:
134 | return toolTipWindow().is_shown
135 |
136 |
137 | def isToolTipInsideOf(widget: QWidget) -> bool:
138 | return widget == toolTipWindow().nowInsideOf()
139 |
140 |
--------------------------------------------------------------------------------
/siui/core/painter.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | import math
4 | from functools import lru_cache
5 | from typing import TYPE_CHECKING
6 |
7 | from PyQt5.QtCore import QPointF, QRectF, Qt
8 | from PyQt5.QtGui import QPainter, QPainterPath
9 |
10 | if TYPE_CHECKING:
11 | from PyQt5.QtGui import QFont, QPaintDevice
12 |
13 | from siui.typing import T_Brush, T_PenStyle, T_RenderHint
14 |
15 |
16 | def createPainter(
17 | paintDevice: QPaintDevice,
18 | renderHint: T_RenderHint = QPainter.RenderHint.Antialiasing,
19 | penStyle: T_PenStyle = Qt.PenStyle.NoPen,
20 | brush: T_Brush = None,
21 | font: QFont | None = None,
22 | ) -> QPainter:
23 | """构造并初始化 QPainter 对象
24 | 应该使用 with 关键字来创建和关闭 QPainter 对象
25 |
26 | 参数:
27 | - parent: QPaintDevice 的子类实例,通常是 QWidget 或 QImage
28 | - renderHint: 指定渲染提示,默认为 QPainter.RenderHint.Antialiasing 标准抗锯齿
29 | - penStyle: Qt.PenStyle 类型,指定画笔样式,默认为 Qt.PenStyle.NoPen
30 | - brushColor: 字符串或 QColor 对象,指定画刷颜色,默认不指定
31 | - font: QFont 对象,指定字体,默认不指定
32 |
33 | 返回:
34 | QPainter 对象实例
35 | """
36 | painter = QPainter(paintDevice)
37 | if renderHint is not None:
38 | painter.setRenderHints(renderHint)
39 |
40 | if penStyle is not None:
41 | painter.setPen(penStyle)
42 |
43 | if brush is not None:
44 | painter.setBrush(brush)
45 |
46 | if font is not None:
47 | painter.setFont(font)
48 |
49 | return painter
50 |
51 |
52 | def _superSin(x: float, power: float = 5.0) -> float:
53 | return math.copysign(abs(math.sin(x)) ** (2 / power), math.sin(x))
54 |
55 |
56 | def _superCos(x: float, power: float = 5.0) -> float:
57 | return math.copysign(abs(math.cos(x)) ** (2 / power), math.cos(x))
58 |
59 |
60 | @lru_cache(maxsize=None)
61 | def _getSuperRoundedPoints(radius_x: float, radius_y: float, power: float, quality: int):
62 | points = []
63 | for i in range(quality + 1):
64 | points.append(QPointF((_superSin(2 * math.pi * i / quality, power) + 0) * radius_x,
65 | (_superCos(2 * math.pi * i / quality, power) + 0) * radius_y))
66 | return points
67 |
68 |
69 | @lru_cache(maxsize=None)
70 | def _cachedGetSuperRoundedRectPath(rect_tuple: tuple,
71 | radius_x: float,
72 | radius_y: float,
73 | power: float,
74 | quality: int) -> QPainterPath:
75 | rect = QRectF(*rect_tuple)
76 | path = QPainterPath()
77 |
78 | if quality == -1:
79 | quality = max(radius_x, radius_y) // 4 * 4
80 |
81 | points = _getSuperRoundedPoints(radius_x, radius_y, power, quality)
82 | inner_rect = QRectF(rect.x() + radius_x, rect.y() + radius_y,
83 | rect.width() - 2 * radius_x, rect.height() - 2 * radius_y)
84 |
85 | q = quality
86 |
87 | path.moveTo(points[q // 4 * 0] + inner_rect.bottomRight())
88 | delta = inner_rect.bottomRight()
89 | for i in range(q // 4 * 0, q // 4 * 1 + 1):
90 | mid_point = (points[i] + points[i + 1]) / 2 + delta
91 | point = points[i] + delta
92 | path.quadTo(point, mid_point)
93 |
94 | delta = inner_rect.topRight()
95 | for i in range(q // 4 * 1, q // 4 * 2 + 1):
96 | mid_point = (points[i] + points[i + 1]) / 2 + delta
97 | point = points[i] + delta
98 | path.quadTo(point, mid_point)
99 |
100 | delta = inner_rect.topLeft()
101 | for i in range(q // 4 * 2, q // 4 * 3 + 1):
102 | mid_point = (points[i] + points[i + 1]) / 2 + delta
103 | point = points[i] + delta
104 | path.quadTo(point, mid_point)
105 |
106 | delta = inner_rect.bottomLeft()
107 | for i in range(q // 4 * 3, q // 4 * 4):
108 | mid_point = (points[i] + points[i + 1]) / 2 + delta
109 | point = points[i] + delta
110 | path.quadTo(point, mid_point)
111 |
112 | path.lineTo(points[-1] + inner_rect.bottomLeft()) # 连接到最后一个点
113 |
114 | return path
115 |
116 |
117 | def getSuperRoundedRectPath(rect: QRectF,
118 | radius_x: float,
119 | radius_y: float,
120 | power: float = 5.0,
121 | quality: int = -1) -> QPainterPath:
122 | """生成并返回一个超椭圆圆角矩形的路径
123 |
124 | 参数:
125 | - radius_x: float 圆角的横轴半径
126 | - radius_y: float 圆角的纵轴半径
127 | - power: float 超椭圆方程的幂数
128 | - quality: int 采样品质,若传入 -1,则根据圆角半径自动选择品质,其他传入值应为 4 的整数倍
129 |
130 | 返回:
131 | QPainterPath 对象实例
132 |
133 | 该函数启用了缓存,密集绘制友好
134 | """
135 |
136 | rect_tuple = (rect.x(), rect.y(), rect.width(), rect.height())
137 | return _cachedGetSuperRoundedRectPath(rect_tuple, radius_x, radius_y, power, quality)
138 |
139 |
140 | __all__ = [
141 | "createPainter", "getSuperRoundedRectPath"
142 | ]
143 |
--------------------------------------------------------------------------------
/siui/core/token.py:
--------------------------------------------------------------------------------
1 | from enum import Enum
2 |
3 | from PyQt5.QtGui import QFont
4 |
5 |
6 | class GlobalFontSize(Enum):
7 | """Tokenized Global Font Size"""
8 |
9 | S = 14
10 | M = 20
11 | L = 24
12 | XL = 32
13 |
14 |
15 | class GlobalFontWeight(Enum):
16 | """Tokenized Global Font Weight"""
17 |
18 | LIGHT = QFont.Weight.Light
19 | NORMAL = QFont.Weight.Normal
20 | MEDIUM = QFont.Weight.Medium
21 | DEMI_BOLD = QFont.Weight.DemiBold
22 | BOLD = QFont.Weight.Bold
23 |
24 |
25 | class FontStyle(Enum):
26 | """Tokenized Font Style"""
27 |
28 | REGULAR = QFont.Style.StyleNormal
29 | ITALIC = QFont.Style.StyleItalic
30 | OBLIQUE = QFont.Style.StyleOblique
31 |
32 |
33 | class GlobalFont(Enum):
34 | """Tokenized Global Font"""
35 |
36 | S_LIGHT = GlobalFontSize.S, GlobalFontWeight.LIGHT, FontStyle.REGULAR
37 | M_LIGHT = GlobalFontSize.M, GlobalFontWeight.LIGHT, FontStyle.REGULAR
38 | L_LIGHT = GlobalFontSize.L, GlobalFontWeight.LIGHT, FontStyle.REGULAR
39 | XL_LIGHT = GlobalFontSize.XL, GlobalFontWeight.LIGHT, FontStyle.REGULAR
40 |
41 | S_LIGHT_ITALIC = GlobalFontSize.S, GlobalFontWeight.LIGHT, FontStyle.ITALIC
42 | M_LIGHT_ITALIC = GlobalFontSize.M, GlobalFontWeight.LIGHT, FontStyle.ITALIC
43 | L_LIGHT_ITALIC = GlobalFontSize.L, GlobalFontWeight.LIGHT, FontStyle.ITALIC
44 | XL_LIGHT_ITALIC = GlobalFontSize.XL, GlobalFontWeight.LIGHT, FontStyle.ITALIC
45 |
46 | S_NORMAL = GlobalFontSize.S, GlobalFontWeight.NORMAL, FontStyle.REGULAR
47 | M_NORMAL = GlobalFontSize.M, GlobalFontWeight.NORMAL, FontStyle.REGULAR
48 | L_NORMAL = GlobalFontSize.L, GlobalFontWeight.NORMAL, FontStyle.REGULAR
49 | XL_NORMAL = GlobalFontSize.XL, GlobalFontWeight.NORMAL, FontStyle.REGULAR
50 |
51 | S_NORMAL_ITALIC = GlobalFontSize.S, GlobalFontWeight.NORMAL, FontStyle.ITALIC
52 | M_NORMAL_ITALIC = GlobalFontSize.M, GlobalFontWeight.NORMAL, FontStyle.ITALIC
53 | L_NORMAL_ITALIC = GlobalFontSize.L, GlobalFontWeight.NORMAL, FontStyle.ITALIC
54 | XL_NORMAL_ITALIC = GlobalFontSize.XL, GlobalFontWeight.NORMAL, FontStyle.ITALIC
55 |
56 | S_MEDIUM = GlobalFontSize.S, GlobalFontWeight.MEDIUM, FontStyle.REGULAR
57 | M_MEDIUM = GlobalFontSize.M, GlobalFontWeight.MEDIUM, FontStyle.REGULAR
58 | L_MEDIUM = GlobalFontSize.L, GlobalFontWeight.MEDIUM, FontStyle.REGULAR
59 | XL_MEDIUM = GlobalFontSize.XL, GlobalFontWeight.MEDIUM, FontStyle.REGULAR
60 |
61 | S_MEDIUM_ITALIC = GlobalFontSize.S, GlobalFontWeight.MEDIUM, FontStyle.ITALIC
62 | M_MEDIUM_ITALIC = GlobalFontSize.M, GlobalFontWeight.MEDIUM, FontStyle.ITALIC
63 | L_MEDIUM_ITALIC = GlobalFontSize.L, GlobalFontWeight.MEDIUM, FontStyle.ITALIC
64 | XL_MEDIUM_ITALIC = GlobalFontSize.XL, GlobalFontWeight.MEDIUM, FontStyle.ITALIC
65 |
66 | S_DEMI_BOLD = GlobalFontSize.S, GlobalFontWeight.DEMI_BOLD, FontStyle.REGULAR
67 | M_DEMI_BOLD = GlobalFontSize.M, GlobalFontWeight.DEMI_BOLD, FontStyle.REGULAR
68 | L_DEMI_BOLD = GlobalFontSize.L, GlobalFontWeight.DEMI_BOLD, FontStyle.REGULAR
69 | XL_DEMI_BOLD = GlobalFontSize.XL, GlobalFontWeight.DEMI_BOLD, FontStyle.REGULAR
70 |
71 | S_DEMI_BOLD_ITALIC = GlobalFontSize.S, GlobalFontWeight.DEMI_BOLD, FontStyle.ITALIC
72 | M_DEMI_BOLD_ITALIC = GlobalFontSize.M, GlobalFontWeight.DEMI_BOLD, FontStyle.ITALIC
73 | L_DEMI_BOLD_ITALIC = GlobalFontSize.L, GlobalFontWeight.DEMI_BOLD, FontStyle.ITALIC
74 | XL_DEMI_BOLD_ITALIC = GlobalFontSize.XL, GlobalFontWeight.DEMI_BOLD, FontStyle.ITALIC
75 |
76 | S_BOLD = GlobalFontSize.S, GlobalFontWeight.BOLD, FontStyle.REGULAR
77 | M_BOLD = GlobalFontSize.M, GlobalFontWeight.BOLD, FontStyle.REGULAR
78 | L_BOLD = GlobalFontSize.L, GlobalFontWeight.BOLD, FontStyle.REGULAR
79 | XL_BOLD = GlobalFontSize.XL, GlobalFontWeight.BOLD, FontStyle.REGULAR
80 |
81 | S_BOLD_ITALIC = GlobalFontSize.S, GlobalFontWeight.BOLD, FontStyle.ITALIC
82 | M_BOLD_ITALIC = GlobalFontSize.M, GlobalFontWeight.BOLD, FontStyle.ITALIC
83 | L_BOLD_ITALIC = GlobalFontSize.L, GlobalFontWeight.BOLD, FontStyle.ITALIC
84 | XL_BOLD_ITALIC = GlobalFontSize.XL, GlobalFontWeight.BOLD, FontStyle.ITALIC
85 |
--------------------------------------------------------------------------------
/siui/gui/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | from .color_group import BrightColorGroup, DarkColorGroup, SiColorGroup
4 | from .font import SiFont
5 | from .icons import GlobalIconPack
6 | from .scale import get_windows_scaling_factor, reload_scale_factor, set_scale_factor
7 |
8 | __all__ = ("SiFont",
9 | "set_scale_factor", "get_windows_scaling_factor", "reload_scale_factor",
10 | "GlobalIconPack",
11 | "BrightColorGroup", "DarkColorGroup", "SiColorGroup")
12 |
13 |
--------------------------------------------------------------------------------
/siui/gui/color_group/__init__.py:
--------------------------------------------------------------------------------
1 | from .bright import BrightColorGroup
2 | from .color_group import SiColorGroup
3 | from .dark import DarkColorGroup
4 |
5 | __all__ = ("BrightColorGroup", "SiColorGroup", "DarkColorGroup")
6 |
7 |
--------------------------------------------------------------------------------
/siui/gui/color_group/bright.py:
--------------------------------------------------------------------------------
1 |
2 | from siui.core import SiColor
3 |
4 | from .color_group import SiColorGroup
5 |
6 |
7 | class BrightColorGroup(SiColorGroup):
8 | def __init__(self):
9 | super().__init__()
10 |
11 | self.assign(SiColor.THEME, "#2accb3")
12 | self.assign(SiColor.THEME_TRANSITION_A, "#2abed8")
13 | self.assign(SiColor.THEME_TRANSITION_B, "#2ad98e")
14 |
15 | self.assign(SiColor.SVG_NORMAL, "#494f4d")
16 | self.assign(SiColor.SVG_THEME, "#53857d")
17 |
18 | self.assign(SiColor.LAYER_DIM, "#60000000")
19 |
20 | self.assign(SiColor.TOOLTIP_BG, "#eff9f9f9")
21 |
22 | self.assign(SiColor.INTERFACE_BG_A, "#d6d6d6")
23 | self.assign(SiColor.INTERFACE_BG_B, "#dddddd")
24 | self.assign(SiColor.INTERFACE_BG_C, "#e5e5e5")
25 | self.assign(SiColor.INTERFACE_BG_D, "#eeeeee")
26 | self.assign(SiColor.INTERFACE_BG_E, "#f6f6f6")
27 |
28 | self.assign(SiColor.TEXT_A, "#171d1b")
29 | self.assign(SiColor.TEXT_B, "#2e3432")
30 | self.assign(SiColor.TEXT_C, "#363d3b")
31 | self.assign(SiColor.TEXT_D, "#3f4644")
32 | self.assign(SiColor.TEXT_E, "#494f4d")
33 | self.assign(SiColor.TEXT_THEME, "#237165")
34 |
35 | self.assign(SiColor.SIDE_MSG_FLASH, "#90FFFFFF")
36 | self.assign(SiColor.SIDE_MSG_THEME_NORMAL, "#242027")
37 | self.assign(SiColor.SIDE_MSG_THEME_SUCCESS, "#519868")
38 | self.assign(SiColor.SIDE_MSG_THEME_INFO, "#855198")
39 | self.assign(SiColor.SIDE_MSG_THEME_WARNING, "#986351")
40 | self.assign(SiColor.SIDE_MSG_THEME_ERROR, "#98515b")
41 |
42 | self.assign(SiColor.MENU_BG, "#e5e5e5")
43 |
44 | # 标题相关
45 | self.assign(SiColor.TITLE_INDICATOR, "#2accb3")
46 | self.assign(SiColor.TITLE_HIGHLIGHT, "#b4ceca")
47 |
48 | # 按钮鼠标相关
49 | self.assign(SiColor.BUTTON_IDLE, "#00FFFFFF")
50 | self.assign(SiColor.BUTTON_HOVER, "#10FFFFFF")
51 | self.assign(SiColor.BUTTON_FLASH, "#20FFFFFF")
52 |
53 | # 按钮外观
54 | self.assign(SiColor.BUTTON_PANEL, "#f6f6f6")
55 | self.assign(SiColor.BUTTON_SHADOW, SiColor.mix(self.fromToken(SiColor.INTERFACE_BG_C), "#000000", 0.9))
56 |
57 | self.assign(SiColor.BUTTON_THEMED_BG_A, "#2abed8")
58 | self.assign(SiColor.BUTTON_THEMED_BG_B, "#2ad98e")
59 | self.assign(SiColor.BUTTON_THEMED_SHADOW_A, "#1d8699")
60 | self.assign(SiColor.BUTTON_THEMED_SHADOW_B, "#1d9963")
61 |
62 | self.assign(SiColor.BUTTON_ON, "#372456")
63 | self.assign(SiColor.BUTTON_OFF, "#562b49")
64 |
65 | self.assign(SiColor.RADIO_BUTTON_UNCHECKED, "#211F25")
66 | self.assign(SiColor.RADIO_BUTTON_CHECKED, "#9c65ae")
67 |
68 | self.assign(SiColor.CHECKBOX_SVG, "#1C191F")
69 | self.assign(SiColor.CHECKBOX_UNCHECKED, "#979797")
70 | self.assign(SiColor.CHECKBOX_CHECKED, "#9c65ae")
71 |
72 | self.assign(SiColor.BUTTON_TEXT_BUTTON_IDLE, "#237165")
73 | self.assign(SiColor.BUTTON_TEXT_BUTTON_FLASH, "#237165")
74 | self.assign(SiColor.BUTTON_TEXT_BUTTON_HOVER, "#fabef8")
75 |
76 | # 长按按钮
77 | self.assign(SiColor.BUTTON_LONG_PRESS_PANEL, "#E76856")
78 | self.assign(SiColor.BUTTON_LONG_PRESS_SHADOW, "#a64a3d")
79 | self.assign(SiColor.BUTTON_LONG_PRESS_PROGRESS, "#ff836f")
80 |
81 | # 开关
82 | self.assign(SiColor.SWITCH_DEACTIVATE, "#D2D2D2")
83 | self.assign(SiColor.SWITCH_ACTIVATE, "#100912")
84 |
85 | # 滚动条
86 | self.assign(SiColor.SCROLL_BAR, "#50FFFFFF")
87 |
88 | # 进度条
89 | self.assign(SiColor.PROGRESS_BAR_TRACK, "#d4d4d4")
90 | self.assign(SiColor.PROGRESS_BAR_PROCESSING, "#4183a3")
91 | self.assign(SiColor.PROGRESS_BAR_COMPLETING, "#e3c15b")
92 | self.assign(SiColor.PROGRESS_BAR_PAUSED, "#a8a8a8")
93 | self.assign(SiColor.PROGRESS_BAR_FLASHES, "#9fFFFFFF")
94 |
--------------------------------------------------------------------------------
/siui/gui/color_group/color_group.py:
--------------------------------------------------------------------------------
1 |
2 | from siui.core import SiColor
3 |
4 |
5 | class SiColorGroup:
6 | def __getitem__(self, item):
7 | return self.colors[item]
8 |
9 | def __init__(self,
10 | overwrite=None,
11 | reference=None):
12 |
13 | self.valid_state = True
14 | self.colors = {}
15 |
16 | if overwrite is not None:
17 | self.overwrite(overwrite)
18 | if reference is None:
19 | self.reference = overwrite.reference
20 | else:
21 | self.reference = reference
22 | else:
23 | self.reference = reference
24 |
25 | def assign(self, token, code):
26 | self.colors[token.name] = code
27 |
28 | def remove(self, token):
29 | if token.name in self.colors.keys():
30 | self.colors.pop(token.name)
31 |
32 | def fromToken(self, token):
33 | if token.name in self.colors.keys() and self.valid_state:
34 | return self.colors[token.name]
35 | if self.reference is None:
36 | raise ValueError(
37 | f"Color under token {token.name} is not assigned yet either in this group or in its reference\n"
38 | f"Valid state: {self.valid_state}"
39 | )
40 | else:
41 | return self.reference.fromToken(token)
42 |
43 | def isAssigned(self, token):
44 | if self.reference is None:
45 | return token.name in self.colors.keys()
46 | else:
47 | return ((token.name in self.colors.keys()) and self.valid_state) or self.reference.isAssigned(token)
48 |
49 | def overwrite(self, color_group):
50 | self.colors.update(color_group.colors)
51 |
52 | def setReference(self, color_group):
53 | self.reference = color_group
54 |
55 | def setValid(self, state):
56 | self.valid_state = state
57 |
58 | def isValid(self):
59 | return self.valid_state
60 |
61 |
--------------------------------------------------------------------------------
/siui/gui/color_group/dark.py:
--------------------------------------------------------------------------------
1 |
2 | from siui.core import SiColor
3 |
4 | from .color_group import SiColorGroup
5 |
6 |
7 | class DarkColorGroup(SiColorGroup):
8 | def __init__(self):
9 | super().__init__()
10 |
11 | self.assign(SiColor.THEME, "#855198")
12 | self.assign(SiColor.THEME_TRANSITION_A, "#52389a")
13 | self.assign(SiColor.THEME_TRANSITION_B, "#9c4e8b")
14 |
15 | self.assign(SiColor.SVG_NORMAL, "#DFDFDF")
16 | self.assign(SiColor.SVG_THEME, "#855198")
17 |
18 | self.assign(SiColor.LAYER_DIM, "#60000000")
19 |
20 | self.assign(SiColor.TOOLTIP_BG, "#ef4C4554")
21 |
22 | self.assign(SiColor.INTERFACE_BG_A, "#1C191F")
23 | self.assign(SiColor.INTERFACE_BG_B, "#25222A")
24 | self.assign(SiColor.INTERFACE_BG_C, "#332E38")
25 | self.assign(SiColor.INTERFACE_BG_D, "#403a46")
26 | self.assign(SiColor.INTERFACE_BG_E, "#4C4554")
27 |
28 | self.assign(SiColor.TEXT_A, "#E5E5E5")
29 | self.assign(SiColor.TEXT_B, "#DFDFDF")
30 | self.assign(SiColor.TEXT_C, "#C7C7C7")
31 | self.assign(SiColor.TEXT_D, "#AFAFAF")
32 | self.assign(SiColor.TEXT_E, "#979797")
33 | self.assign(SiColor.TEXT_THEME, "#c58bc2")
34 |
35 | self.assign(SiColor.SIDE_MSG_FLASH, "#90FFFFFF")
36 | self.assign(SiColor.SIDE_MSG_THEME_NORMAL, "#4C4554")
37 | self.assign(SiColor.SIDE_MSG_THEME_SUCCESS, "#519868")
38 | self.assign(SiColor.SIDE_MSG_THEME_INFO, "#855198")
39 | self.assign(SiColor.SIDE_MSG_THEME_WARNING, "#986351")
40 | self.assign(SiColor.SIDE_MSG_THEME_ERROR, "#98515b")
41 |
42 | self.assign(SiColor.MENU_BG, "#332E38")
43 |
44 | # 标题相关
45 | self.assign(SiColor.TITLE_INDICATOR, "#c58bc2")
46 | self.assign(SiColor.TITLE_HIGHLIGHT, "#52324E")
47 |
48 | # 按钮鼠标相关
49 | self.assign(SiColor.BUTTON_IDLE, "#00FFFFFF")
50 | self.assign(SiColor.BUTTON_HOVER, "#10FFFFFF")
51 | self.assign(SiColor.BUTTON_FLASH, "#20FFFFFF")
52 |
53 | # 按钮外观
54 | self.assign(SiColor.BUTTON_PANEL, "#4C4554")
55 | self.assign(SiColor.BUTTON_SHADOW, SiColor.mix(self.fromToken(SiColor.INTERFACE_BG_C), "#000000", 0.9))
56 |
57 | self.assign(SiColor.BUTTON_THEMED_BG_A, "#52389a")
58 | self.assign(SiColor.BUTTON_THEMED_BG_B, "#9c4e8b")
59 | self.assign(SiColor.BUTTON_THEMED_SHADOW_A, "#372456")
60 | self.assign(SiColor.BUTTON_THEMED_SHADOW_B, "#562b49")
61 |
62 | self.assign(SiColor.BUTTON_ON, "#372456")
63 | self.assign(SiColor.BUTTON_OFF, "#562b49")
64 |
65 | self.assign(SiColor.RADIO_BUTTON_UNCHECKED, "#211F25")
66 | self.assign(SiColor.RADIO_BUTTON_CHECKED, "#9c65ae")
67 |
68 | self.assign(SiColor.CHECKBOX_SVG, "#1C191F")
69 | self.assign(SiColor.CHECKBOX_UNCHECKED, "#979797")
70 | self.assign(SiColor.CHECKBOX_CHECKED, "#9c65ae")
71 |
72 | self.assign(SiColor.BUTTON_TEXT_BUTTON_IDLE, "#c58bc2")
73 | self.assign(SiColor.BUTTON_TEXT_BUTTON_FLASH, "#c58bc2")
74 | self.assign(SiColor.BUTTON_TEXT_BUTTON_HOVER, "#fabef8")
75 |
76 | # 长按按钮
77 | self.assign(SiColor.BUTTON_LONG_PRESS_PANEL, "#932a48")
78 | self.assign(SiColor.BUTTON_LONG_PRESS_SHADOW, "#642d41")
79 | self.assign(SiColor.BUTTON_LONG_PRESS_PROGRESS, "#DA3462")
80 |
81 | # 开关
82 | self.assign(SiColor.SWITCH_DEACTIVATE, "#D2D2D2")
83 | self.assign(SiColor.SWITCH_ACTIVATE, "#100912")
84 |
85 | # 滚动条
86 | self.assign(SiColor.SCROLL_BAR, "#50FFFFFF")
87 |
88 | # 进度条
89 | self.assign(SiColor.PROGRESS_BAR_TRACK, "#252229")
90 | self.assign(SiColor.PROGRESS_BAR_PROCESSING, "#66CBFF")
91 | self.assign(SiColor.PROGRESS_BAR_COMPLETING, "#FED966")
92 | self.assign(SiColor.PROGRESS_BAR_PAUSED, "#7F7F7F")
93 | self.assign(SiColor.PROGRESS_BAR_FLASHES, "#FFFFFF")
94 |
--------------------------------------------------------------------------------
/siui/gui/font.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | from PyQt5.QtGui import QFont
6 | from PyQt5.QtWidgets import qApp
7 |
8 | from siui.core.token import FontStyle, GlobalFont, GlobalFontSize, GlobalFontWeight
9 |
10 | if TYPE_CHECKING:
11 | from collections.abc import Sequence
12 |
13 |
14 | class SiFont:
15 | """SiUI Font Class
16 |
17 | You can use low-level API to customize fonts details,
18 | or use tokenized global fonts to quickly create fonts.
19 | """
20 | Weight = QFont.Weight
21 |
22 | @staticmethod
23 | def getFont(
24 | families=None,
25 | size: int = 14,
26 | weight: QFont.Weight = QFont.Weight.Normal,
27 | italic: bool = False,
28 | hinting_preference: QFont.HintingPreference = QFont.PreferFullHinting
29 | ) -> QFont:
30 | """Low-level API for creating font instance
31 |
32 | Application-level configuration takes the highest priority,
33 | and it is recommended to use the tokenized Hier-level API.
34 |
35 | Args:
36 | - families: 字体族列表,如果指定了应用程序级别的全局配置,则会覆盖默认字体家族
37 | - size: 字体大小
38 | - weight: 字体粗细
39 | - italic: 是否斜体
40 | - hinting_preference: 字体 Hinting 偏好, 默认为 PreferFullHinting
41 |
42 | Returns:
43 | - QFont: 字体实例
44 |
45 | """
46 | if families is None:
47 | families = (
48 | qApp.font().families() or
49 | ["Segoe UI", "Microsoft YaHei", "San Francisco Fonts", ".PingFang TC", "PingFang SC"]
50 | )
51 |
52 | font = QFont()
53 | font.setFamilies(families)
54 | font.setPixelSize(size)
55 | font.setWeight(weight)
56 | font.setItalic(italic)
57 | font.setHintingPreference(hinting_preference)
58 | return font
59 |
60 | @staticmethod
61 | def fromToken(size: GlobalFontSize, weight: GlobalFontWeight, style: FontStyle) -> QFont:
62 | """通过已经令牌化的字体属性构造字体"""
63 |
64 | return SiFont.getFont(size=size.value, weight=weight.value, italic=style == FontStyle.ITALIC)
65 |
66 | @staticmethod
67 | def tokenized(token: GlobalFont) -> QFont:
68 | """返回一个已经被令牌化的全局字体"""
69 |
70 | try:
71 | return SiFont.fromToken(*token.value)
72 | except KeyError:
73 | raise ValueError(f"Invalid token: {token}")
74 |
--------------------------------------------------------------------------------
/siui/gui/icons/__init__.py:
--------------------------------------------------------------------------------
1 | from .parser import GlobalIconPack
2 |
3 | __all__ = ("GlobalIconPack",)
4 |
--------------------------------------------------------------------------------
/siui/gui/icons/parser.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from PyQt5.QtCore import QByteArray, QSize, Qt
4 | from PyQt5.QtGui import QPainter, QPixmap, QIcon
5 | from PyQt5.QtSvg import QSvgRenderer
6 |
7 |
8 | class GlobalIconPack:
9 | current_module_path = os.path.dirname(os.path.abspath(__file__))
10 | package_folder_path = os.path.join(current_module_path, "packages")
11 |
12 | def __init__(self):
13 | self.default_color = None
14 |
15 | self.icons = {}
16 | self.icons_classified = {
17 | "__unclassified__": {}
18 | }
19 |
20 | # load internal icon packages
21 | self.reload_internals()
22 |
23 | def setDefaultColor(self, code) -> None:
24 | self.default_color = code
25 |
26 | @property
27 | def defaultColor(self) -> str:
28 | return self.default_color
29 |
30 | def reload_internals(self) -> None:
31 | for package_filename in os.listdir(self.package_folder_path):
32 | full_path = os.path.join(self.package_folder_path, package_filename)
33 | if os.path.isfile(full_path):
34 | self.load_from_file(full_path)
35 |
36 | def load_from_file(self, path) -> None:
37 | class_name = os.path.basename(path)
38 | self.append_class(class_name)
39 | with open(path, encoding="utf-8") as file:
40 | for line in file.readlines():
41 | if line[0:2] == "##":
42 | continue
43 | if line.strip() == "":
44 | continue
45 |
46 | line = line.strip()
47 | icon_name, icon_data = line.split("////")
48 | self.append(icon_name, icon_data, class_name)
49 |
50 | def append_class(self, class_name, force=False) -> None:
51 | if class_name in self.icons_classified.keys() and (force is False):
52 | raise ValueError(f"Class name {class_name} is already exist.")
53 | self.icons_classified[class_name] = {}
54 |
55 | def append(self, name, data, class_name: str = "__unclassified__") -> None:
56 | self.icons[name] = data
57 | self.icons_classified[class_name][name] = data
58 |
59 | def get(self, name, color_code: str = None) -> bytes:
60 | color_code = self.default_color if color_code is None else color_code
61 | return self.icons[name].replace("<<>>", color_code).encode()
62 |
63 | def getFromData(self, data, color_code: str = None) -> bytes:
64 | color_code = self.default_color if color_code is None else color_code
65 | return data.replace("<<>>", color_code).encode()
66 |
67 | def getByteArray(self, name, color_code: str = None) -> QByteArray:
68 | svg_bytes = self.get(name, color_code)
69 | return QByteArray(svg_bytes)
70 |
71 | def getDict(self, class_name=None) -> dict:
72 | """
73 | Get dictionary of an icon package.
74 | If class name is assigned, returns the specific package dictionary.
75 | If class name is None, returns a dictionary that contains all icons.
76 | """
77 | if class_name is None:
78 | return self.icons
79 | else:
80 | return self.icons_classified[class_name]
81 |
82 | def getClassNames(self) -> dict.keys:
83 | return self.icons_classified.keys()
84 |
85 | def toPixmap(self, name: str, size: QSize = QSize(64, 64), color_code: str = None):
86 | svg_bytes = self.get(name, color_code)
87 | pixmap = QPixmap(size)
88 | pixmap.fill(Qt.transparent)
89 | painter = QPainter(pixmap)
90 | painter.setRenderHint(QPainter.RenderHint.SmoothPixmapTransform)
91 | svg_renderer = QSvgRenderer(svg_bytes)
92 | svg_renderer.render(painter)
93 | painter.end()
94 | return pixmap
95 |
96 | def toIcon(self, name: str, size: QSize = QSize(64, 64), color_code: str = None) -> QIcon:
97 | return QIcon(self.toPixmap(name, size, color_code))
98 |
99 |
--------------------------------------------------------------------------------
/siui/gui/scale.py:
--------------------------------------------------------------------------------
1 | import ctypes
2 | import os
3 |
4 |
5 | def get_windows_scaling_factor():
6 | try:
7 | # 调用 Windows API 函数获取缩放比例
8 | user32 = ctypes.windll.user32
9 | user32.SetProcessDPIAware()
10 | scaling_factor = user32.GetDpiForSystem()
11 |
12 | # 计算缩放比例
13 | return scaling_factor / 96.0
14 |
15 | except Exception as e:
16 | print("无法获取缩放比例,设置为1,错误:", e)
17 | return 1
18 |
19 |
20 | def reload_scale_factor():
21 | set_scale_factor(get_windows_scaling_factor(), identity="Windows API")
22 |
23 |
24 | def set_scale_factor(factor, identity="External calls"):
25 | os.environ["QT_SCALE_FACTOR"] = str(factor)
26 | print("已将环境变量 QT_SCALE_FACTOR 设为", factor, f" (来源: {identity})")
27 |
--------------------------------------------------------------------------------
/siui/templates/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/siui/templates/__init__.py
--------------------------------------------------------------------------------
/siui/templates/application/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/siui/templates/application/__init__.py
--------------------------------------------------------------------------------
/siui/templates/application/application.py:
--------------------------------------------------------------------------------
1 |
2 | from PyQt5.QtWidgets import QMainWindow
3 |
4 | from siui.components.tooltip import ToolTipWindow
5 | from siui.components.widgets.abstracts import SiWidget
6 | from siui.core import SiGlobal
7 | from siui.templates.application.components.layer.layer_child_page.layer_child_page import LayerChildPage
8 | from siui.templates.application.components.layer.layer_left_global_drawer.layer_left_global_drawer import (
9 | LayerLeftGlobalDrawer,
10 | )
11 | from siui.templates.application.components.layer.layer_main.layer_main import LayerMain
12 | from siui.templates.application.components.layer.layer_modal_dialog.layer_modal_dialog import LayerModalDialog
13 | from siui.templates.application.components.layer.layer_overlays.layer_overlays import LayerOverLays
14 | from siui.templates.application.components.layer.layer_right_message_sidebar.layer_right_message_sidebar import (
15 | LayerRightMessageSidebar,
16 | )
17 |
18 |
19 | class SiliconApplication(QMainWindow):
20 | """
21 | SiliconUI 应用程序模板,包含工具提示窗口
22 | """
23 | def __init__(self, *args, **kwargs):
24 | super().__init__(*args, **kwargs)
25 |
26 | # 添加全局窗口
27 | SiGlobal.siui.windows["MAIN_WINDOW"] = self
28 | SiGlobal.siui.windows["TOOL_TIP"] = ToolTipWindow()
29 | SiGlobal.siui.windows["TOOL_TIP"].show()
30 | SiGlobal.siui.windows["TOOL_TIP"].setOpacity(0)
31 |
32 | # 初始化窗口
33 | self.resize(1200, 700)
34 | self.setWindowTitle("Silicon Application Template")
35 |
36 | # 层的组
37 | self.group_main_interface = SiWidget(self)
38 | self.groups_ = {
39 | "MAIN_INTERFACE": self.group_main_interface
40 | }
41 |
42 | # 构建界面
43 | self.layer_main = LayerMain(self.group_main_interface)
44 | self.layer_child_page = LayerChildPage(self.group_main_interface)
45 |
46 | self.layer_left_global_drawer = LayerLeftGlobalDrawer(self)
47 | self.layer_right_message_sidebar = LayerRightMessageSidebar(self)
48 | self.layer_modal_dialog = LayerModalDialog(self)
49 | self.layer_overlays = LayerOverLays(self)
50 |
51 | def groups(self):
52 | return self.groups_
53 |
54 | def layerMain(self):
55 | return self.layer_main
56 |
57 | def LayerRightMessageSidebar(self):
58 | return self.layer_right_message_sidebar
59 |
60 | def layerChildPage(self):
61 | return self.layer_child_page
62 |
63 | def layerModalDialog(self):
64 | return self.layer_modal_dialog
65 |
66 | def layerLeftGlobalDrawer(self):
67 | return self.layer_left_global_drawer
68 |
69 | def resizeEvent(self, event):
70 | super().resizeEvent(event)
71 | size = event.size()
72 | w, h = size.width(), size.height()
73 |
74 | self.group_main_interface.resize(w, h)
75 |
76 | # Set the maximum height of the sidebar to prevent performance from dropping when too many message boxes exist.
77 | self.layer_right_message_sidebar.setMaximumHeight(event.size().height())
78 | self.layer_right_message_sidebar.adjustSize()
79 |
80 | self.layer_main.resize(event.size())
81 | self.layer_child_page.resize(event.size())
82 | self.layer_right_message_sidebar.setGeometry(w - 400, 80, 400, self.layer_right_message_sidebar.height())
83 | self.layer_modal_dialog.resize(event.size())
84 | self.layer_left_global_drawer.resize(event.size())
85 | self.layer_overlays.resize(event.size())
86 |
--------------------------------------------------------------------------------
/siui/templates/application/components/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/siui/templates/application/components/__init__.py
--------------------------------------------------------------------------------
/siui/templates/application/components/dialog/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/siui/templates/application/components/dialog/__init__.py
--------------------------------------------------------------------------------
/siui/templates/application/components/dialog/modal.py:
--------------------------------------------------------------------------------
1 | from siui.components import SiWidget, SiLabel, SiSvgLabel, SiDenseVContainer
2 | from siui.core import SiColor
3 | from siui.core import SiGlobal
4 |
5 |
6 | class SiModalDialog(SiWidget):
7 | def __init__(self, *args, **kwargs):
8 | super().__init__(*args, **kwargs)
9 |
10 | self.body_padding_h = 43
11 | self.theme_padding_h = 26
12 | self.content_padding_v = 32
13 | self.button_padding_v = 24
14 | self.theme_label_top_height = 2
15 | self.theme_label_bottom_height = 0
16 | self.setFixedWidth(460)
17 |
18 | self.theme_label = SiLabel(self)
19 | self.theme_label.setFixedStyleSheet("border-radius: 8px")
20 | self.theme_label.setColor(self.getColor(SiColor.THEME))
21 |
22 | self.body_content_label = SiLabel(self)
23 | self.body_content_label.setObjectName("body_content_label")
24 |
25 | self.body_button_label = SiLabel(self)
26 | self.body_button_label.setObjectName("body_button_label")
27 |
28 | self.content_container = SiDenseVContainer(self.body_content_label)
29 | self.content_container.setAdjustWidgetsSize(True)
30 |
31 | self.button_container = SiDenseVContainer(self.body_button_label)
32 | self.button_container.setAdjustWidgetsSize(True)
33 | self.button_container.setSpacing(8)
34 |
35 | self.icon_ = SiSvgLabel(self.content_container)
36 | self.icon_.resize(64, 64)
37 | self.icon_.setSvgSize(64, 64)
38 |
39 | def icon(self):
40 | return self.icon_
41 |
42 | def contentContainer(self):
43 | return self.content_container
44 |
45 | def buttonContainer(self):
46 | return self.button_container
47 |
48 | def reloadStyleSheet(self):
49 | super().reloadStyleSheet()
50 | self.theme_label.setColor(self.getColor(SiColor.THEME))
51 | self.body_content_label.setStyleSheet(
52 | "#body_content_label {"
53 | " border-radius: 8px;"
54 | f" background-color: {self.getColor(SiColor.INTERFACE_BG_B)};"
55 | f" border: 1px solid {self.getColor(SiColor.INTERFACE_BG_C)};"
56 | "}"
57 | )
58 | self.body_button_label.setStyleSheet(
59 | "#body_button_label {"
60 | " border-radius: 8px;"
61 | f" background-color: {self.getColor(SiColor.INTERFACE_BG_C)};"
62 | f" border: 1px solid {self.getColor(SiColor.INTERFACE_BG_C)};"
63 | "}"
64 |
65 | )
66 |
67 | def adjustSize(self):
68 | self.content_container.setFixedWidth(self.width() - 2 * self.body_padding_h)
69 | self.button_container.setFixedWidth(self.width() - 2 * self.body_padding_h)
70 | self.content_container.adjustSize()
71 | self.button_container.adjustSize()
72 |
73 | self.body_content_label.setGeometry(
74 | 0,
75 | self.theme_label_top_height,
76 | self.width(),
77 | self.content_container.height() + 2 * self.content_padding_v + self.button_container.height() + 2 * self.button_padding_v
78 | )
79 |
80 | self.body_button_label.setGeometry(
81 | 0,
82 | self.theme_label_top_height + self.content_container.height() + 2 * self.content_padding_v,
83 | self.width(),
84 | self.button_container.height() + 2 * self.button_padding_v
85 | )
86 |
87 | self.content_container.move(self.body_padding_h, self.content_padding_v)
88 | self.button_container.move(self.body_padding_h, self.button_padding_v)
89 | self.theme_label.setGeometry(
90 | self.theme_padding_h,
91 | 0,
92 | self.width() - 2 * self.theme_padding_h,
93 | self.content_container.height() + 2 * self.content_padding_v + self.button_container.height() + 2 * self.button_padding_v + self.theme_label_top_height + self.theme_label_bottom_height
94 | )
95 | self.icon_.move(self.content_container.width() - self.icon_.width(), 0)
96 | self.resize(self.width(), self.theme_label.height())
97 |
--------------------------------------------------------------------------------
/siui/templates/application/components/layer/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/siui/templates/application/components/layer/__init__.py
--------------------------------------------------------------------------------
/siui/templates/application/components/layer/global_drawer.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt
2 | from PyQt5.QtWidgets import QWidget
3 |
4 | from siui.components import SiLabel, SiWidget, SiTitledWidgetGroup
5 | from siui.components.page import SiPage
6 | from siui.templates.application.components.layer.layer import SiLayer
7 |
8 |
9 | class Drawer(SiWidget):
10 | def resizeEvent(self, event):
11 | super().resizeEvent(event)
12 | for child in self.children():
13 | if isinstance(child, QWidget):
14 | child.resize(event.size())
15 |
16 |
17 | class SiLayerDrawer(SiLayer):
18 | def __init__(self, *args, **kwargs):
19 | super().__init__(*args, **kwargs)
20 |
21 | self.is_opened = False
22 |
23 | self.drawer = Drawer(self)
24 | self.drawer_panel = SiLabel(self.drawer)
25 | self.drawer_page = SiPage(self.drawer)
26 |
27 | self.setDrawerWidth(400)
28 | self.closeLayer()
29 |
30 | def isOpened(self):
31 | return self.is_opened
32 |
33 | def setOpened(self, state):
34 | self.is_opened = state
35 |
36 | def setDrawerWidth(self, width):
37 | self.drawer.resize(width, self.drawer.height())
38 |
39 | def showLayer(self):
40 | super().showLayer()
41 | self.setAttribute(Qt.WA_TransparentForMouseEvents, False)
42 | self.setOpened(True)
43 |
44 | def closeLayer(self):
45 | super().closeLayer()
46 | self.setAttribute(Qt.WA_TransparentForMouseEvents, True)
47 | self.setOpened(False)
48 |
49 | def resizeEvent(self, event):
50 | super().resizeEvent(event)
51 | self.drawer.resize(self.drawer.width(), event.size().height())
52 |
--------------------------------------------------------------------------------
/siui/templates/application/components/layer/layer.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt, pyqtSignal
2 |
3 | from siui.components.widgets.abstracts.widget import SiWidget
4 | from siui.components.widgets.label import SiLabel
5 | from siui.core import SiColor
6 |
7 |
8 | class SiLabelHasClickedSignal(SiLabel):
9 | clicked = pyqtSignal()
10 |
11 | def mousePressEvent(self, event):
12 | super().mousePressEvent(event)
13 | if event.button() == Qt.LeftButton:
14 | self.clicked.emit()
15 | event.accept()
16 |
17 |
18 | class SiLayer(SiWidget):
19 | closed = pyqtSignal()
20 | showed = pyqtSignal()
21 |
22 | def __init__(self, *args, **kwargs):
23 | super().__init__(*args, **kwargs)
24 |
25 | self.close_on_dim_clicked = True
26 |
27 | self.dim_ = SiLabelHasClickedSignal(self)
28 | self.dim_.setColor(SiColor.trans(self.getColor(SiColor.LAYER_DIM), 0.0))
29 | self.dim_.clicked.connect(self.on_dim_layer_clicked)
30 |
31 | def setCloseOnDimClicked(self, on):
32 | self.close_on_dim_clicked = on
33 |
34 | def on_dim_layer_clicked(self):
35 | if self.close_on_dim_clicked is True:
36 | self.closeLayer()
37 |
38 | def closeLayer(self):
39 | self.closed.emit()
40 | self.hideDimMask()
41 |
42 | def showLayer(self):
43 | self.showed.emit()
44 | self.show()
45 | self.showDimMask()
46 |
47 | def showDimMask(self, ani=True):
48 | if ani is True:
49 | self.dim_.setColorTo(SiColor.trans(self.getColor(SiColor.LAYER_DIM), 1.0))
50 | else:
51 | self.dim_.setColor(SiColor.trans(self.getColor(SiColor.LAYER_DIM), 1.0))
52 |
53 | def hideDimMask(self, ani=True):
54 | if ani is True:
55 | self.dim_.setColorTo(SiColor.trans(self.getColor(SiColor.LAYER_DIM), 0.0))
56 | else:
57 | self.dim_.setColor(SiColor.trans(self.getColor(SiColor.LAYER_DIM), 0.0))
58 |
59 | def resizeEvent(self, event):
60 | super().resizeEvent(event)
61 | self.dim_.resize(event.size())
62 |
--------------------------------------------------------------------------------
/siui/templates/application/components/layer/layer_child_page/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/siui/templates/application/components/layer/layer_child_page/__init__.py
--------------------------------------------------------------------------------
/siui/templates/application/components/layer/layer_child_page/layer_child_page.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt, QTimer
2 |
3 | from ..layer import SiLayer
4 |
5 |
6 | class LayerChildPage(SiLayer):
7 | def __init__(self, *args, **kwargs):
8 | super().__init__(*args, **kwargs)
9 |
10 | self.child_page = None
11 | self.setAttribute(Qt.WA_TransparentForMouseEvents, True)
12 |
13 | def childPage(self):
14 | return self.child_page
15 |
16 | def setChildPage(self, page):
17 | if self.childPage() is not None:
18 | page.deleteLater()
19 | return
20 |
21 | self.child_page = page
22 | self.child_page.animationGroup().fromToken("move").setFactor(1/4)
23 | self.child_page.animationGroup().fromToken("move").setBias(0.5)
24 | self.child_page.setParent(self)
25 | self.child_page.adjustSize()
26 | self.child_page.move((self.width() - self.childPage().width()) // 2, self.height())
27 | self.child_page.show()
28 | self.showLayer()
29 |
30 | def showLayer(self):
31 | super().showLayer()
32 | self.showChildPage()
33 |
34 | def closeLayer(self):
35 | super().closeLayer()
36 | self.closeChildPage()
37 |
38 | def showChildPage(self):
39 | self.setAttribute(Qt.WA_TransparentForMouseEvents, False)
40 | self.child_page.moveTo((self.width() - self.childPage().width()) // 2, self.height() - self.childPage().height())
41 |
42 | def closeChildPage(self):
43 | self.setAttribute(Qt.WA_TransparentForMouseEvents, True)
44 | self.child_page.moveTo((self.width() - self.childPage().width()) // 2, self.height())
45 | self.child_page.delete_timer = QTimer()
46 | self.child_page.delete_timer.singleShot(500, self.child_page.deleteLater)
47 | self.child_page = None
48 |
49 | def resizeEvent(self, event):
50 | super().resizeEvent(event)
51 | if self.child_page is not None:
52 | self.child_page.adjustSize()
53 | self.child_page.move((self.width() - self.childPage().width()) // 2, self.height() - self.childPage().height())
54 |
--------------------------------------------------------------------------------
/siui/templates/application/components/layer/layer_left_global_drawer/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/siui/templates/application/components/layer/layer_left_global_drawer/__init__.py
--------------------------------------------------------------------------------
/siui/templates/application/components/layer/layer_left_global_drawer/layer_left_global_drawer.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt
2 |
3 | from siui.components import SiLabel, SiTitledWidgetGroup, SiWidget
4 | from siui.components.slider.slider import SiSliderH
5 | from siui.components.combobox import SiComboBox
6 | from siui.core import SiColor
7 | from siui.core import SiGlobal
8 |
9 | from ..global_drawer import SiLayerDrawer
10 |
11 |
12 | class LayerLeftGlobalDrawer(SiLayerDrawer):
13 | def __init__(self, *args, **kwargs):
14 | super().__init__(*args, **kwargs)
15 | self.drawer.move(-self.drawer.width(), 0)
16 |
17 | self.drawer_widget_group = SiTitledWidgetGroup(self)
18 | self.drawer_widget_group.setSpacing(8)
19 |
20 | self.drawer_page.setPadding(48)
21 | self.drawer_page.setTitle("全局左侧抽屉")
22 | self.drawer_page.title.setContentsMargins(32, 0, 0, 0)
23 | self.drawer_page.setScrollAlignment(Qt.AlignLeft)
24 |
25 | with self.drawer_widget_group as group:
26 | group.addTitle("全局性")
27 |
28 | self.text_label = SiLabel(self)
29 | self.text_label.setTextColor(self.getColor(SiColor.TEXT_D))
30 | self.text_label.setWordWrap(True)
31 | self.text_label.setText("这里是全局抽屉,无论在何种情况下,该抽屉被打开时都会令界面发生侧移,保证抽屉正常展开\n\n"
32 | "不同于其他页面,全局抽屉推荐为唯一的,全局抽屉中的控件推荐为静态的")
33 | self.text_label.setFixedHeight(128)
34 |
35 | group.addWidget(self.text_label)
36 |
37 | with self.drawer_widget_group as group:
38 | group.addTitle("声音")
39 |
40 | self.label_output_device = SiLabel(self)
41 | self.label_output_device.setTextColor(self.getColor(SiColor.TEXT_C))
42 | self.label_output_device.setText("输出设备")
43 |
44 | self.demo_output_device = SiComboBox(self)
45 | self.demo_output_device.resize(256, 32)
46 | self.demo_output_device.addOption("默认设备")
47 | self.demo_output_device.addOption("RealTek(R) Output")
48 | self.demo_output_device.addOption("姬霓太美(R) Output")
49 | self.demo_output_device.menu().setShowIcon(False)
50 | self.demo_output_device.menu().setIndex(0)
51 |
52 | self.label_slider_1 = SiLabel(self)
53 | self.label_slider_1.setTextColor(self.getColor(SiColor.TEXT_C))
54 | self.label_slider_1.setText("总音量")
55 |
56 | self.demo_slider_1 = SiSliderH(self)
57 | self.demo_slider_1.resize(0, 16)
58 | self.demo_slider_1.setMinimum(0)
59 | self.demo_slider_1.setMaximum(100)
60 | self.demo_slider_1.setValue(80, move_to=False)
61 |
62 | self.label_slider_2 = SiLabel(self)
63 | self.label_slider_2.setTextColor(self.getColor(SiColor.TEXT_C))
64 | self.label_slider_2.setText("音乐音量")
65 |
66 | self.demo_slider_2 = SiSliderH(self)
67 | self.demo_slider_2.resize(0, 16)
68 | self.demo_slider_2.setMinimum(0)
69 | self.demo_slider_2.setMaximum(100)
70 | self.demo_slider_2.setValue(100, move_to=False)
71 |
72 | self.label_slider_3 = SiLabel(self)
73 | self.label_slider_3.setTextColor(self.getColor(SiColor.TEXT_C))
74 | self.label_slider_3.setText("音效音量")
75 |
76 | self.demo_slider_3 = SiSliderH(self)
77 | self.demo_slider_3.resize(0, 16)
78 | self.demo_slider_3.setMinimum(0)
79 | self.demo_slider_3.setMaximum(100)
80 | self.demo_slider_3.setValue(61, move_to=False)
81 |
82 | group.addWidget(self.label_output_device)
83 | group.addWidget(self.demo_output_device)
84 | group.addPlaceholder(8)
85 | group.addWidget(self.label_slider_1)
86 | group.addWidget(self.demo_slider_1)
87 | group.addPlaceholder(8)
88 | group.addWidget(self.label_slider_2)
89 | group.addWidget(self.demo_slider_2)
90 | group.addPlaceholder(8)
91 | group.addWidget(self.label_slider_3)
92 | group.addWidget(self.demo_slider_3)
93 |
94 | group.addPlaceholder(64)
95 |
96 | self.drawer_page.setAttachment(self.drawer_widget_group)
97 |
98 | def setOpened(self, state):
99 | super().setOpened(state)
100 | if state:
101 | self.drawer.moveTo(0, 0)
102 | else:
103 | self.drawer.moveTo(-self.drawer.width(), 0)
104 |
105 | def reloadStyleSheet(self):
106 | super().reloadStyleSheet()
107 | self.drawer_panel.setStyleSheet(
108 | f"background-color: {self.getColor(SiColor.INTERFACE_BG_C)};"
109 | f"border-right: 1px solid {self.getColor(SiColor.INTERFACE_BG_D)}"
110 | )
111 |
112 | def showLayer(self):
113 | super().showLayer()
114 | SiGlobal.siui.windows["MAIN_WINDOW"].groups()["MAIN_INTERFACE"].moveTo(100, 0)
115 |
116 | def closeLayer(self):
117 | super().closeLayer()
118 | SiGlobal.siui.windows["MAIN_WINDOW"].groups()["MAIN_INTERFACE"].moveTo(0, 0)
119 |
--------------------------------------------------------------------------------
/siui/templates/application/components/layer/layer_main/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/siui/templates/application/components/layer/layer_main/__init__.py
--------------------------------------------------------------------------------
/siui/templates/application/components/layer/layer_main/layer_main.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt
2 |
3 | from siui.components import SiDenseHContainer, SiDenseVContainer, SiLabel, SiPixLabel
4 | from siui.core import GlobalFont, Si, SiColor
5 | from siui.gui import SiFont
6 | from siui.templates.application.components.page_view import PageView
7 |
8 | from ..layer import SiLayer
9 |
10 |
11 | class LayerMain(SiLayer):
12 | def __init__(self, *args, **kwargs):
13 | super().__init__(*args, **kwargs)
14 |
15 | # 整个窗口的垫底标签
16 | self.background_label = SiLabel(self)
17 | self.background_label.setFixedStyleSheet("border-radius: 8px")
18 |
19 | # -> 垂直容器,上方是标题,下方是窗口内容
20 | self.container_title_and_content = SiDenseVContainer(self)
21 | self.container_title_and_content.setSpacing(0)
22 | self.container_title_and_content.setAdjustWidgetsSize(True)
23 |
24 | # -> 标题栏处的水平容器,左侧是图标和标题,右侧是操作按钮
25 | self.container_title = SiDenseHContainer(self)
26 | self.container_title.setSpacing(0)
27 | self.container_title.setAlignment(Qt.AlignCenter)
28 | self.container_title.setFixedHeight(64)
29 |
30 | # 应用内图标
31 | self.app_icon = SiPixLabel(self)
32 | self.app_icon.resize(24, 24)
33 | self.app_icon.load("./img/logo_new.png")
34 |
35 | # 应用标题
36 | self.app_title = SiLabel(self)
37 | self.app_title.setAlignment(Qt.AlignVCenter | Qt.AlignLeft)
38 | self.app_title.setFont(SiFont.tokenized(GlobalFont.S_NORMAL))
39 | self.app_title.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged)
40 | self.app_title.setText("Silicon 应用模版")
41 |
42 | self.container_title.addPlaceholder(2)
43 | self.container_title.addPlaceholder(16)
44 | self.container_title.addWidget(self.app_icon)
45 | self.container_title.addPlaceholder(16)
46 | self.container_title.addWidget(self.app_title)
47 |
48 | self.page_view = PageView(self)
49 |
50 | # <- 添加到垂直容器
51 | self.container_title_and_content.addWidget(self.container_title)
52 | self.container_title_and_content.addWidget(self.page_view)
53 |
54 | # 隐藏阴影层,因为没有任何用
55 | self.dim_.hide()
56 |
57 | def reloadStyleSheet(self):
58 | self.background_label.setStyleSheet(
59 | f"background-color: {self.getColor(SiColor.INTERFACE_BG_A)};"
60 | f"border: 1px solid {self.getColor(SiColor.INTERFACE_BG_B)};"
61 | )
62 | self.app_title.setStyleSheet(f"color: {self.getColor(SiColor.TEXT_B)}")
63 |
64 | def setTitle(self, title):
65 | self.app_title.setText(title)
66 |
67 | def addPage(self, page, icon, hint: str, side="top"):
68 | """
69 | 添加新页面
70 | :param page: 页面控件
71 | :param icon: 页面按钮的 svg 数据或路径
72 | :param hint: 页面按钮的工具提示
73 | :param side: 页面按钮置于哪一侧
74 | """
75 | self.page_view.addPage(page, icon, hint, side)
76 |
77 | def setPage(self, index):
78 | """ Set current page by index """
79 | self.page_view.stacked_container.setCurrentIndex(index)
80 |
81 | def resizeEvent(self, event):
82 | super().resizeEvent(event)
83 | self.background_label.resize(event.size())
84 | self.container_title_and_content.resize(event.size())
85 | self.page_view.resize(event.size().width(), event.size().height() - 64)
86 | self.dim_.resize(event.size())
87 |
--------------------------------------------------------------------------------
/siui/templates/application/components/layer/layer_modal_dialog/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/siui/templates/application/components/layer/layer_modal_dialog/__init__.py
--------------------------------------------------------------------------------
/siui/templates/application/components/layer/layer_modal_dialog/layer_modal_dialog.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt
2 |
3 | from siui.components import SiWidget
4 | from siui.core import Si
5 |
6 | from ..layer import SiLayer
7 |
8 |
9 | class LayerModalDialog(SiLayer):
10 | def __init__(self, *args, **kwargs):
11 | super().__init__(*args, **kwargs)
12 |
13 | self.dialog_ = None
14 | self.dialog_frame = SiWidget(self)
15 | self.dialog_frame.hideCenterWidgetFadeOut()
16 | self.dialog_frame.animationGroup().fromToken("showing").setBias(0.08)
17 | self.setAttribute(Qt.WA_TransparentForMouseEvents, True)
18 |
19 | def dialog(self):
20 | return self.dialog_
21 |
22 | def setDialog(self, dialog):
23 | if self.dialog() is not None:
24 | return
25 |
26 | self.dialog_ = dialog
27 | self.dialog_.show()
28 | self.dialog_frame.setCenterWidget(self.dialog_)
29 | self.showLayer()
30 |
31 | def showLayer(self):
32 | super().showLayer()
33 | self.showDialog()
34 |
35 | def closeLayer(self):
36 | super().closeLayer()
37 | self.closeDialog()
38 |
39 | def showDialog(self):
40 | self.setAttribute(Qt.WA_TransparentForMouseEvents, False)
41 | self.dialog_frame.setSiliconWidgetFlag(Si.DeleteCenterWidgetOnCenterWidgetHidden, False)
42 | self.dialog_frame.showCenterWidgetFadeIn()
43 |
44 | def closeDialog(self):
45 | self.setAttribute(Qt.WA_TransparentForMouseEvents, True)
46 | self.dialog_frame.hideCenterWidgetFadeOut()
47 | self.dialog_frame.setSiliconWidgetFlag(Si.DeleteCenterWidgetOnCenterWidgetHidden)
48 | self.dialog_ = None
49 |
50 | def resizeEvent(self, event):
51 | super().resizeEvent(event)
52 | self.dialog_frame.resize(event.size())
53 |
--------------------------------------------------------------------------------
/siui/templates/application/components/layer/layer_overlays/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/siui/templates/application/components/layer/layer_overlays/__init__.py
--------------------------------------------------------------------------------
/siui/templates/application/components/layer/layer_overlays/layer_overlays.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtCore import Qt, QTimer
2 | from PyQt5.QtGui import QFont
3 | from PyQt5.QtWidgets import QGraphicsOpacityEffect
4 |
5 | from siui.components import SiDenseVContainer, SiLabel
6 | from siui.components.widgets.expands import SiVExpandWidget
7 | from siui.core import Si, SiColor, SiExpAccelerateAnimation, SiQuickEffect, SiGlobal
8 | from siui.gui import SiFont
9 |
10 | from ..layer import SiLayer
11 |
12 |
13 | class DenseVContainerBG(SiDenseVContainer):
14 | def __init__(self, *args, **kwargs):
15 | super().__init__(*args, **kwargs)
16 |
17 | self.background = SiLabel(self)
18 | self.background.setFixedStyleSheet("border-radius: 12px")
19 | self.background.setColor(SiColor.trans(self.getColor(SiColor.INTERFACE_BG_A), 0.9))
20 |
21 | def resizeEvent(self, event):
22 | super().resizeEvent(event)
23 | self.background.resize(event.size())
24 |
25 |
26 | class StateChangeOverlay(SiVExpandWidget):
27 | def __init__(self, *args, **kwargs):
28 | super().__init__(*args, **kwargs)
29 |
30 | self.container = DenseVContainerBG(self)
31 |
32 | self.title = SiLabel(self)
33 | self.title.setFont(SiFont.getFont(size=18, weight=QFont.Weight.Normal))
34 | self.title.setTextColor(self.getColor(SiColor.TEXT_B))
35 | self.title.setAlignment(Qt.AlignCenter)
36 | self.title.setFixedHeight(24)
37 | self.title.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged)
38 |
39 | self.subtitle = SiLabel(self)
40 | self.subtitle.setFont(SiFont.getFont(size=15, weight=QFont.Weight.DemiBold))
41 | self.subtitle.setTextColor(self.getColor(SiColor.TEXT_THEME))
42 | self.subtitle.setAlignment(Qt.AlignCenter)
43 | self.subtitle.setFixedHeight(16)
44 | self.subtitle.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged)
45 |
46 | self.div = SiLabel(self)
47 | self.div.setFixedStyleSheet("border-radius: 1px")
48 | self.div.resize(168, 2)
49 | self.div.setColor("#20FFFFFF")
50 |
51 | self.tip = SiLabel(self)
52 | self.tip.setFont(SiFont.getFont(size=12, weight=QFont.Weight.Normal))
53 | self.tip.setTextColor(self.getColor(SiColor.TEXT_C))
54 | self.tip.setAlignment(Qt.AlignCenter)
55 | self.tip.setFixedHeight(16)
56 | self.tip.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged)
57 |
58 | self.container.setSpacing(0)
59 | self.container.setAlignment(Qt.AlignCenter)
60 | self.container.addPlaceholder(16)
61 | self.container.addWidget(self.title)
62 | self.container.addPlaceholder(4)
63 | self.container.addWidget(self.subtitle)
64 | self.container.addPlaceholder(16)
65 | self.container.addWidget(self.div)
66 | self.container.addPlaceholder(10)
67 | self.container.addWidget(self.tip)
68 |
69 | self.setAttachment(self.container)
70 |
71 | self.fade_out_timer = QTimer(self)
72 | self.fade_out_timer.setSingleShot(True)
73 | self.fade_out_timer.setInterval(2000)
74 | self.fade_out_timer.timeout.connect(lambda: self.expandTo(0))
75 | self.fade_out_timer.timeout.connect(lambda: self.setOpacityTo(0))
76 |
77 | self.animationGroup().fromToken("expand").setAccelerateFunction(lambda x: (x / 10) ** 5)
78 |
79 | self.animation_opacity = SiExpAccelerateAnimation(self)
80 | self.animation_opacity.setAccelerateFunction(lambda x: (x / 10) ** 3)
81 | self.animation_opacity.setFactor(1/2)
82 | self.animation_opacity.setBias(0.01)
83 | self.animation_opacity.setCurrent(1)
84 | self.animation_opacity.setTarget(1)
85 | self.animation_opacity.ticked.connect(self.on_opacity_changed)
86 |
87 | def on_opacity_changed(self, opacity):
88 | effect = QGraphicsOpacityEffect()
89 | effect.setOpacity(opacity)
90 | self.setGraphicsEffect(effect)
91 |
92 | def emerge(self):
93 | self.expandTo(1)
94 | self.setOpacityTo(1)
95 | self.animation_opacity.start()
96 | self.fade_out_timer.start()
97 |
98 | def resizeEvent(self, event):
99 | super().resizeEvent(event)
100 |
101 | def setContent(self, title, subtitle, tip, emerge=True):
102 | self.title.setText(title)
103 | self.subtitle.setText(subtitle)
104 | self.tip.setText(tip)
105 | if emerge:
106 | self.emerge()
107 |
108 |
109 | class LayerOverLays(SiLayer):
110 | def __init__(self, *args, **kwargs):
111 | super().__init__(*args, **kwargs)
112 |
113 | self.setAttribute(Qt.WA_TransparentForMouseEvents, True)
114 | self.state_change_overlay = StateChangeOverlay(self)
115 | self.state_change_overlay.adjustSize()
116 | self.state_change_overlay.setFixedSize(216, 120)
117 |
118 | def resizeEvent(self, event):
119 | super().resizeEvent(event)
120 | self.state_change_overlay.move((self.width() - self.state_change_overlay.width()) // 2,
121 | int((self.height() - self.state_change_overlay.height()) * 0.785))
122 |
123 | self.state_change_overlay.setContent(
124 | "设置窗口大小", f"{self.width()}×{self.height()}", "无快捷键"
125 | )
126 |
127 |
--------------------------------------------------------------------------------
/siui/templates/application/components/layer/layer_right_message_sidebar/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/siui/templates/application/components/layer/layer_right_message_sidebar/__init__.py
--------------------------------------------------------------------------------
/siui/templates/application/components/layer/layer_right_message_sidebar/layer_right_message_sidebar.py:
--------------------------------------------------------------------------------
1 | from typing import Union
2 |
3 | from siui.components import SiLabel, SiMasonryContainer
4 | from siui.core import GlobalFont, Si, SiColor, SiQuickEffect
5 | from siui.gui import SiFont
6 |
7 | from .messagebox import SiSideMessageBox
8 |
9 |
10 | class MessageSidebar(SiMasonryContainer):
11 | def __init__(self, *args, **kwargs):
12 | super().__init__(*args, **kwargs)
13 |
14 | self.setColumns(1)
15 | self.setColumnWidth(400)
16 | self.setSpacing(horizontal=None, vertical=16)
17 |
18 | self.debug_label = SiLabel(self)
19 | # self.debug_label.setColor("#20FF0000")
20 |
21 | def sendMessageBox(self, message_box):
22 | self.addWidget(message_box)
23 | message_box.setFixedWidth(self.width()-20)
24 | message_box.move(80, self.height() - message_box.height())
25 | message_box.show()
26 |
27 | def send(self,
28 | text: str,
29 | title: str = None,
30 | msg_type: int = 0,
31 | icon: Union[bytes, str] = None,
32 | slot=None,
33 | close_on_clicked=True,
34 | fold_after: int = None):
35 | """ Create a simple message box which only has a label and send it to sidebar """
36 | new_message_box = SiSideMessageBox(self)
37 | new_message_box.setMessageType(msg_type)
38 | new_message_box.setFixedWidth(self.width()-20)
39 |
40 | if slot is not None:
41 | new_message_box.clicked.connect(slot)
42 |
43 | if close_on_clicked is True:
44 | new_message_box.clicked.connect(new_message_box.closeLater)
45 |
46 | if title is None:
47 | label = SiLabel(self)
48 | label.setFixedWidth(380 - new_message_box.content().theme_wing_width - 32)
49 | label.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged)
50 | label.setWordWrap(True)
51 | label.setFont(SiFont.tokenized(GlobalFont.S_NORMAL))
52 | label.setFixedStyleSheet(
53 | "padding-top: 16px;"
54 | "padding-bottom: 16px;"
55 | "padding-left: 12px;"
56 | "padding-right: 12px;"
57 | "color: {}".format(self.getColor(SiColor.TEXT_D))
58 | )
59 | label.setText(text)
60 | new_message_box.content().container().addWidget(label)
61 | else:
62 | new_message_box.content().container().setSpacing(0)
63 | title_label = SiLabel(self)
64 | title_label.setFixedWidth(380 - new_message_box.content().theme_wing_width - 32)
65 | title_label.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged)
66 | title_label.setWordWrap(True)
67 | title_label.setFont(SiFont.tokenized(GlobalFont.S_BOLD))
68 | title_label.setFixedStyleSheet(
69 | "padding-top: 16px;"
70 | "padding-bottom: 1px;"
71 | "padding-left: 12px;"
72 | "padding-right: 12px;"
73 | "color: {}".format(self.getColor(SiColor.TEXT_B))
74 | )
75 | title_label.setText(title)
76 |
77 | description_label = SiLabel(self)
78 | description_label.setFixedWidth(380 - new_message_box.content().theme_wing_width - 32)
79 | description_label.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged)
80 | description_label.setWordWrap(True)
81 | description_label.setFont(SiFont.tokenized(GlobalFont.S_NORMAL))
82 | description_label.setFixedStyleSheet(
83 | "padding-top: 1px;"
84 | "padding-bottom: 16px;"
85 | "padding-left: 12px;"
86 | "padding-right: 12px;"
87 | "color: {}".format(self.getColor(SiColor.TEXT_D))
88 | )
89 | description_label.setText(text)
90 |
91 | new_message_box.content().container().addWidget(title_label)
92 | new_message_box.content().container().addWidget(description_label)
93 |
94 | if fold_after is not None:
95 | new_message_box.setFoldAfter(fold_after)
96 |
97 | if icon is not None:
98 | new_message_box.content().themeIcon().load(icon)
99 |
100 | new_message_box.adjustSize()
101 | self.sendMessageBox(new_message_box)
102 |
103 | def resizeEvent(self, event):
104 | super().resizeEvent(event)
105 | self.debug_label.resize(event.size())
106 |
107 |
108 | class LayerRightMessageSidebar(MessageSidebar):
109 | def __init__(self, *args, **kwargs):
110 | super().__init__(*args, **kwargs)
111 |
112 | SiQuickEffect.applyDropShadowOn(self,
113 | color=(28, 25, 31, 200),
114 | blur_radius=64)
--------------------------------------------------------------------------------
/siui/templates/application/components/message/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChinaIceF/PyQt-SiliconUI/35f0eff570decac7d1b84e9f53d1582c13e19006/siui/templates/application/components/message/__init__.py
--------------------------------------------------------------------------------
/siui/templates/application/components/message/sidebar.py:
--------------------------------------------------------------------------------
1 |
2 | from typing import Union
3 |
4 | from siui.components import SiLabel
5 | from siui.components.widgets.container import SiMasonryContainer
6 | from siui.core import GlobalFont, Si, SiColor
7 | from siui.gui import SiFont
8 | from siui.templates.application.components.message.box import SiSideMessageBox
9 |
10 |
11 | class MessageSidebar(SiMasonryContainer):
12 | def __init__(self, *args, **kwargs):
13 | super().__init__(*args, **kwargs)
14 |
15 | self.setColumns(1)
16 | self.setColumnWidth(400)
17 | self.setSpacing(horizontal=None, vertical=16)
18 |
19 | # self.debug_label = SiLabel(self)
20 | # self.debug_label.setColor("#20FF0000")
21 |
22 | def sendMessageBox(self, message_box):
23 | self.addWidget(message_box)
24 | message_box.setFixedWidth(self.width()-20)
25 | message_box.move(80, self.height() - message_box.height())
26 | message_box.show()
27 |
28 | def send(self,
29 | text: str,
30 | title: str = None,
31 | msg_type: int = 0,
32 | icon: Union[bytes, str] = None,
33 | slot=None,
34 | close_on_clicked=True,
35 | fold_after: int = None):
36 | """ Create a simple message box which only has a label and send it to sidebar """
37 | new_message_box = SiSideMessageBox(self)
38 | new_message_box.setMessageType(msg_type)
39 | new_message_box.setFixedWidth(self.width()-20)
40 |
41 | if slot is not None:
42 | new_message_box.clicked.connect(slot)
43 |
44 | if close_on_clicked is True:
45 | new_message_box.clicked.connect(new_message_box.closeLater)
46 |
47 | if title is None:
48 | label = SiLabel(self)
49 | label.setFixedWidth(380 - new_message_box.content().theme_wing_width - 32)
50 | label.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged)
51 | label.setWordWrap(True)
52 | label.setFont(SiFont.tokenized(GlobalFont.S_NORMAL))
53 | label.setFixedStyleSheet(
54 | "padding-top: 16px;"
55 | "padding-bottom: 16px;"
56 | "padding-left: 12px;"
57 | "padding-right: 12px;"
58 | f"color: {self.getColor(SiColor.TEXT_D)}"
59 | )
60 | label.setText(text)
61 | new_message_box.content().container().addWidget(label)
62 | else:
63 | new_message_box.content().container().setSpacing(0)
64 | title_label = SiLabel(self)
65 | title_label.setFixedWidth(380 - new_message_box.content().theme_wing_width - 32)
66 | title_label.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged)
67 | title_label.setWordWrap(True)
68 | title_label.setFont(SiFont.tokenized(GlobalFont.S_BOLD))
69 | title_label.setFixedStyleSheet(
70 | "padding-top: 16px;"
71 | "padding-bottom: 1px;"
72 | "padding-left: 12px;"
73 | "padding-right: 12px;"
74 | f"color: {self.getColor(SiColor.TEXT_B)}"
75 | )
76 | title_label.setText(title)
77 |
78 | description_label = SiLabel(self)
79 | description_label.setFixedWidth(380 - new_message_box.content().theme_wing_width - 32)
80 | description_label.setSiliconWidgetFlag(Si.AdjustSizeOnTextChanged)
81 | description_label.setWordWrap(True)
82 | description_label.setFont(SiFont.tokenized(GlobalFont.S_NORMAL))
83 | description_label.setFixedStyleSheet(
84 | "padding-top: 1px;"
85 | "padding-bottom: 16px;"
86 | "padding-left: 12px;"
87 | "padding-right: 12px;"
88 | f"color: {self.getColor(SiColor.TEXT_D)}"
89 | )
90 | description_label.setText(text)
91 |
92 | new_message_box.content().container().addWidget(title_label)
93 | new_message_box.content().container().addWidget(description_label)
94 |
95 | if fold_after is not None:
96 | new_message_box.setFoldAfter(fold_after)
97 |
98 | if icon is not None:
99 | new_message_box.content().themeIcon().load(icon)
100 |
101 | new_message_box.adjustSize()
102 | self.sendMessageBox(new_message_box)
103 |
104 | def resizeEvent(self, event):
105 | super().resizeEvent(event)
106 | # self.debug_label.resize(event.size())
107 |
--------------------------------------------------------------------------------
/siui/templates/application/components/page_view/__init__.py:
--------------------------------------------------------------------------------
1 | from siui.templates.application.components.page_view.page_view import PageView
--------------------------------------------------------------------------------
/siui/typing.py:
--------------------------------------------------------------------------------
1 | """
2 | ## This module defines global shared types
3 |
4 | Use Python's Type Hint syntax, reference:
5 | - [`typing`](https://docs.python.org/3/library/typing.html)
6 | - [`PEP 484`](https://www.python.org/dev/peps/pep-0484/)
7 | - [`PEP 526`](https://www.python.org/dev/peps/pep-0526/)
8 | """
9 |
10 | from typing import Optional, Union
11 |
12 | from PyQt5.QtCore import QObject, Qt
13 | from PyQt5.QtGui import QColor, QGradient, QPainter, QPen
14 | from PyQt5.QtWidgets import QWidget
15 | from typing_extensions import TypeAlias
16 |
17 | T_WidgetParent: TypeAlias = Optional[QWidget]
18 | """Type of widget parent"""
19 |
20 | T_ObjectParent: TypeAlias = Optional[QObject]
21 | """Type of object parent"""
22 |
23 | T_PenStyle: TypeAlias = Union[QPen, Qt.PenStyle, QColor, Qt.GlobalColor]
24 | """Type of QPen style"""
25 |
26 | T_Brush: TypeAlias = Optional[Union[QGradient, QColor, Qt.GlobalColor]]
27 | """Type of QBrush"""
28 |
29 | T_RenderHint: TypeAlias = Optional[Union[QPainter.RenderHint, int]]
30 | """Type of QPainter.RenderHint"""
--------------------------------------------------------------------------------