pyside-quasar 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyside_quasar-0.2.0/PKG-INFO +215 -0
- pyside_quasar-0.2.0/README.md +168 -0
- pyside_quasar-0.2.0/pyproject.toml +180 -0
- pyside_quasar-0.2.0/setup.cfg +4 -0
- pyside_quasar-0.2.0/src/pyside_quasar/__init__.py +281 -0
- pyside_quasar-0.2.0/src/pyside_quasar/assets/fonts/Roboto-Regular.ttf +0 -0
- pyside_quasar-0.2.0/src/pyside_quasar/assets/icons/check.svg +0 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/__init__.py +4 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/containers/__init__.py +10 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/containers/card.py +284 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/containers/collapse.py +0 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/containers/dialog.py +373 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/containers/drawer.py +0 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/containers/grid.py +0 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/containers/tabs.py +449 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/data/__init__.py +0 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/data/table/__init__.py +0 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/data/table/delegate.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/data/table/model.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/data/table/view.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/feedback/__init__.py +8 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/feedback/notification.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/feedback/position.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/feedback/registry.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/feedback/toast.py +551 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/feedback/tooltip.py +446 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/primitives/__init__.py +16 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/primitives/avatar.py +630 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/primitives/badge.py +554 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/primitives/button.py +816 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/primitives/checkbox.py +563 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/primitives/chip.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/primitives/input.py +492 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/primitives/progress.py +380 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/primitives/radio.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/primitives/slider.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/components/primitives/switch.py +432 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/__init__.py +25 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/base/__init__.py +10 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/base/widget.py +70 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/events/__init__.py +0 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/events/bus.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/i18n/__init__.py +0 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/i18n/locales/en_US.json +0 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/i18n/locales/zh_CN.json +0 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/i18n/translator.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/router/__init__.py +4 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/router/guard.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/router/router.py +42 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/router/transition.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/state/__init__.py +0 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/state/slices/app_slice.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/state/slices/user_slice.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/state/store.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/theme/__init__.py +6 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/theme/contrast.py +24 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/theme/manager.py +95 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/theme/palette.py +15 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/theme/tokens.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/utils/__init__.py +0 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/utils/animation.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/utils/color.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/utils/dpr.py +15 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/utils/geometry.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/utils/painter.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/validation/__init__.py +5 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/validation/form.py +36 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/validation/rule.py +28 -0
- pyside_quasar-0.2.0/src/pyside_quasar/core/validation/validator.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/layouts/__init__.py +0 -0
- pyside_quasar-0.2.0/src/pyside_quasar/layouts/auth_layout.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/layouts/blank_layout.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/layouts/main_layout.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/py.typed +0 -0
- pyside_quasar-0.2.0/src/pyside_quasar/templates/__init__.py +0 -0
- pyside_quasar-0.2.0/src/pyside_quasar/templates/dashboard_page.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/templates/login_page.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar/templates/settings_page.py +2 -0
- pyside_quasar-0.2.0/src/pyside_quasar.egg-info/PKG-INFO +215 -0
- pyside_quasar-0.2.0/src/pyside_quasar.egg-info/SOURCES.txt +81 -0
- pyside_quasar-0.2.0/src/pyside_quasar.egg-info/dependency_links.txt +1 -0
- pyside_quasar-0.2.0/src/pyside_quasar.egg-info/requires.txt +26 -0
- pyside_quasar-0.2.0/src/pyside_quasar.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyside-quasar
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: The Quasar Framework for PySide — Material Design components, pure QPainter, zero QSS.
|
|
5
|
+
Author-email: eagleye-china <zdt168@sina.cn>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/eagleye-china/pyside-quasar
|
|
8
|
+
Project-URL: Documentation, https://eagleye-china.github.io/pyside-quasar
|
|
9
|
+
Project-URL: Repository, https://github.com/eagleye-china/pyside-quasar
|
|
10
|
+
Project-URL: Issues, https://github.com/eagleye-china/pyside-quasar/issues
|
|
11
|
+
Project-URL: Changelog, https://github.com/eagleye-china/pyside-quasar/blob/main/CHANGELOG.md
|
|
12
|
+
Keywords: pyside6,qt6,material-design,quasar,ui-framework,desktop,qpainter,pyside
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: X11 Applications :: Qt
|
|
15
|
+
Classifier: Environment :: Win32 (MS Windows)
|
|
16
|
+
Classifier: Environment :: MacOS X
|
|
17
|
+
Classifier: Intended Audience :: Developers
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Topic :: Software Development :: User Interfaces
|
|
24
|
+
Classifier: Topic :: Desktop Environment
|
|
25
|
+
Classifier: Typing :: Typed
|
|
26
|
+
Requires-Python: >=3.10
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
Requires-Dist: PySide6>=6.6
|
|
29
|
+
Requires-Dist: typing-extensions>=4.0; python_version < "3.13"
|
|
30
|
+
Provides-Extra: test
|
|
31
|
+
Requires-Dist: pytest>=7.4; extra == "test"
|
|
32
|
+
Requires-Dist: pytest-qt>=4.2; extra == "test"
|
|
33
|
+
Requires-Dist: pytest-cov>=4.1; extra == "test"
|
|
34
|
+
Provides-Extra: lint
|
|
35
|
+
Requires-Dist: mypy>=1.5; extra == "lint"
|
|
36
|
+
Requires-Dist: ruff>=0.7.0; extra == "lint"
|
|
37
|
+
Requires-Dist: pre-commit>=3.4; extra == "lint"
|
|
38
|
+
Requires-Dist: import-linter>=2.0; extra == "lint"
|
|
39
|
+
Provides-Extra: docs
|
|
40
|
+
Requires-Dist: mkdocs-material>=9.4; extra == "docs"
|
|
41
|
+
Requires-Dist: mkdocstrings[python]>=0.24; extra == "docs"
|
|
42
|
+
Requires-Dist: mkdocs-gen-files>=0.5; extra == "docs"
|
|
43
|
+
Provides-Extra: build
|
|
44
|
+
Requires-Dist: nuitka>=2.4; extra == "build"
|
|
45
|
+
Provides-Extra: dev
|
|
46
|
+
Requires-Dist: pyside-quasar[build,docs,lint,test]; extra == "dev"
|
|
47
|
+
|
|
48
|
+
# PySide-Quasar ⚛️
|
|
49
|
+
|
|
50
|
+
> **Enterprise-grade UI components for PySide. Quasar aesthetics, Pure QPainter, Zero QSS.**
|
|
51
|
+
|
|
52
|
+
**English** | [简体中文](README_zh.md)
|
|
53
|
+
|
|
54
|
+
[](https://pypi.org/project/pyside-quasar/)
|
|
55
|
+
[](https://pypi.org/project/pyside-quasar/)
|
|
56
|
+
[](LICENSE)
|
|
57
|
+
[](https://github.com/eagleye-china/pyside-quasar)
|
|
58
|
+
|
|
59
|
+
**PySide-Quasar** is a modern, enterprise-grade UI component framework for PySide. Inspired by the design language of Vue's *Quasar Framework*, it brings Material Design aesthetics to desktop applications using **pure `QPainter` rendering** with **ZERO QSS (Qt Style Sheets) dependencies**.
|
|
60
|
+
|
|
61
|
+
It eliminates the common pain points of QSS—such as cross-platform rendering inconsistencies, performance bottlenecks, and style breakages—making it the perfect choice for industrial control panels, monitoring dashboards, and complex enterprise desktop clients.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 📸 Gallery
|
|
66
|
+
|
|
67
|
+
> 💡 *Here is a preview of the core components. (Replace the image URLs below with your actual GIFs!)*
|
|
68
|
+
|
|
69
|
+
| Components | Showcase |
|
|
70
|
+
| :---: | :---: |
|
|
71
|
+
| **Buttons & Checkboxes** | <img src="https://via.placeholder.com/600x300/1E1E1E/D4D4D4?text=Buttons+and+Checkboxes+GIF" alt="Buttons and Checkboxes" width="400"/> |
|
|
72
|
+
| **Dialogs & Badges** | <img src="https://via.placeholder.com/600x300/1E1E1E/D4D4D4?text=Dialog+and+Badge+GIF" alt="Dialog and Badge" width="400"/> |
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 🤔 Why PySide-Quasar? (The "Zero QSS" Philosophy)
|
|
77
|
+
|
|
78
|
+
Traditional PySide/PyQt applications rely heavily on QSS. While fine for small apps, QSS scales poorly in enterprise systems. Here is why we went completely QSS-free:
|
|
79
|
+
|
|
80
|
+
| Feature | Traditional QSS Approach | **PySide-Quasar (Our Approach)** |
|
|
81
|
+
| :--- | :--- | :--- |
|
|
82
|
+
| **Rendering** | OS-dependent, often buggy with complex gradients. | **Pixel-perfect** across Windows, macOS, and Linux. |
|
|
83
|
+
| **Performance** | High CPU usage during rapid updates (e.g., industrial data). | **Blazing fast** with optimized native `QPainter`. |
|
|
84
|
+
| **High-DPI (4K)** | Blurry borders, broken scaling, jagged edges. | **Crisp & Sharp** automatically adapts to devicePixelRatio. |
|
|
85
|
+
| **Maintenance** | Hundreds of lines of unstructured CSS-like strings. | **Clean Python** with strongly-typed APIs and theme engines. |
|
|
86
|
+
| **PySide7/8 Future**| Style breakages requiring extensive rewrites. | **Future-proof**, seamlessly migrates to future PySide versions. |
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## ✨ Core Features
|
|
91
|
+
|
|
92
|
+
- 🚀 **Zero QSS Dependency** – Everything is drawn natively via `QPainter`.
|
|
93
|
+
- 🧩 **Quasar-Inspired Design** – Beautiful Material Design components with smooth micro-animations.
|
|
94
|
+
- 🔮 **Future-Proof API** – Built on an abstraction layer. Currently binds to `PySide6`, but fully prepared for `PySide7/8`.
|
|
95
|
+
- 🖥️ **4K / Retina Ready** – Deeply optimized for High-DPI screens. No more blurry icons or jagged lines.
|
|
96
|
+
- 🎨 **Dynamic Theme Engine** – Native Light/Dark mode support. Automatic high-contrast text calculation.
|
|
97
|
+
- 🛡️ **Enterprise-Grade Typed** – 100% Type hints. Perfect for PyCharm/VSCode intellisense and strict CI pipelines.
|
|
98
|
+
- 📦 **Lightweight & Packable** – No WebViews, no heavy assets. Very friendly for `PyInstaller`.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 📦 Installation
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
pip install pyside-quasar
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Dependencies:**
|
|
109
|
+
- `PySide6 >= 6.6.0`
|
|
110
|
+
- `typing-extensions`
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## 🚀 Quick Start
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
import sys
|
|
118
|
+
from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout
|
|
119
|
+
from pyside_quasar.components import Button, Checkbox, Dialog
|
|
120
|
+
from pyside_quasar.theme import QuasarTheme
|
|
121
|
+
|
|
122
|
+
if __name__ == "__main__":
|
|
123
|
+
app = QApplication(sys.argv)
|
|
124
|
+
|
|
125
|
+
# 1. Apply Dark Theme (Native rendering)
|
|
126
|
+
QuasarTheme.apply_dark()
|
|
127
|
+
|
|
128
|
+
# 2. Create your main window
|
|
129
|
+
win = QMainWindow()
|
|
130
|
+
win.resize(800, 600)
|
|
131
|
+
win.setWindowTitle("PySide-Quasar Demo")
|
|
132
|
+
|
|
133
|
+
# 3. Use pure QPainter components
|
|
134
|
+
central = QWidget()
|
|
135
|
+
layout = QVBoxLayout(central)
|
|
136
|
+
|
|
137
|
+
btn = Button(text="Open Dialog", color="primary", size="lg")
|
|
138
|
+
chk = Checkbox(text="Enable Advanced Settings", checked=True)
|
|
139
|
+
|
|
140
|
+
layout.addWidget(btn)
|
|
141
|
+
layout.addWidget(chk)
|
|
142
|
+
win.setCentralWidget(central)
|
|
143
|
+
|
|
144
|
+
win.show()
|
|
145
|
+
sys.exit(app.exec())
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## 🧩 Components Ecosystem
|
|
151
|
+
|
|
152
|
+
We are actively expanding the ecosystem. Here is the current status:
|
|
153
|
+
|
|
154
|
+
| Module | Stable Components | In Development |
|
|
155
|
+
| :--- | :--- | :--- |
|
|
156
|
+
| **Primitives** | `Button`, `Checkbox`, `Avatar`, `Badge` | `Input`, `Switch`, `Select` |
|
|
157
|
+
| **Containers** | `Dialog` | `Card`, `Tabs`, `Drawer` |
|
|
158
|
+
| **Feedback** | - | `Toast`, `Notify`, `Progress` |
|
|
159
|
+
| **Data** | - | `Table`, `Pagination` |
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 🎨 Theming System
|
|
164
|
+
|
|
165
|
+
Say goodbye to messy stylesheets. Control your entire app's look with Python.
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
from pyside_quasar.theme import QuasarTheme
|
|
169
|
+
|
|
170
|
+
# 1. Toggle Light/Dark mode
|
|
171
|
+
QuasarTheme.apply_light()
|
|
172
|
+
QuasarTheme.apply_dark()
|
|
173
|
+
|
|
174
|
+
# 2. Set your enterprise brand color
|
|
175
|
+
QuasarTheme.set_brand_color("#1976D2")
|
|
176
|
+
|
|
177
|
+
# 3. Global border radius configuration
|
|
178
|
+
QuasarTheme.set_border_radius(6)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## 📐 Roadmap & Version Strategy
|
|
184
|
+
|
|
185
|
+
Because our package name **`pyside-quasar`** does not contain a version number, you are protected from ecosystem churn.
|
|
186
|
+
|
|
187
|
+
- **`v1.x`** – Active development, binding to **PySide6**.
|
|
188
|
+
- **`v2.x`** – Seamless transition to **PySide7** (Zero code changes for UI layers).
|
|
189
|
+
- **`v3.x`** – Future-ready for **PySide8**.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 🤝 Contributing
|
|
194
|
+
|
|
195
|
+
We welcome contributions from the global community! Whether it's a bug report, a new component, or a documentation fix, your help is appreciated.
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
# Clone the repository
|
|
199
|
+
git clone https://github.com/eagleye-china/pyside-quasar.git
|
|
200
|
+
cd pyside-quasar
|
|
201
|
+
|
|
202
|
+
# Install in editable mode for development
|
|
203
|
+
pip install -e .
|
|
204
|
+
|
|
205
|
+
# Build the package
|
|
206
|
+
python -m build
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
If you find this project useful, please consider giving it a ⭐️ on GitHub! It means a lot to us.
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## 📜 License
|
|
214
|
+
|
|
215
|
+
MIT License. Commercial use is allowed. See the [LICENSE](LICENSE) file for details.
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# PySide-Quasar ⚛️
|
|
2
|
+
|
|
3
|
+
> **Enterprise-grade UI components for PySide. Quasar aesthetics, Pure QPainter, Zero QSS.**
|
|
4
|
+
|
|
5
|
+
**English** | [简体中文](README_zh.md)
|
|
6
|
+
|
|
7
|
+
[](https://pypi.org/project/pyside-quasar/)
|
|
8
|
+
[](https://pypi.org/project/pyside-quasar/)
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
[](https://github.com/eagleye-china/pyside-quasar)
|
|
11
|
+
|
|
12
|
+
**PySide-Quasar** is a modern, enterprise-grade UI component framework for PySide. Inspired by the design language of Vue's *Quasar Framework*, it brings Material Design aesthetics to desktop applications using **pure `QPainter` rendering** with **ZERO QSS (Qt Style Sheets) dependencies**.
|
|
13
|
+
|
|
14
|
+
It eliminates the common pain points of QSS—such as cross-platform rendering inconsistencies, performance bottlenecks, and style breakages—making it the perfect choice for industrial control panels, monitoring dashboards, and complex enterprise desktop clients.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 📸 Gallery
|
|
19
|
+
|
|
20
|
+
> 💡 *Here is a preview of the core components. (Replace the image URLs below with your actual GIFs!)*
|
|
21
|
+
|
|
22
|
+
| Components | Showcase |
|
|
23
|
+
| :---: | :---: |
|
|
24
|
+
| **Buttons & Checkboxes** | <img src="https://via.placeholder.com/600x300/1E1E1E/D4D4D4?text=Buttons+and+Checkboxes+GIF" alt="Buttons and Checkboxes" width="400"/> |
|
|
25
|
+
| **Dialogs & Badges** | <img src="https://via.placeholder.com/600x300/1E1E1E/D4D4D4?text=Dialog+and+Badge+GIF" alt="Dialog and Badge" width="400"/> |
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 🤔 Why PySide-Quasar? (The "Zero QSS" Philosophy)
|
|
30
|
+
|
|
31
|
+
Traditional PySide/PyQt applications rely heavily on QSS. While fine for small apps, QSS scales poorly in enterprise systems. Here is why we went completely QSS-free:
|
|
32
|
+
|
|
33
|
+
| Feature | Traditional QSS Approach | **PySide-Quasar (Our Approach)** |
|
|
34
|
+
| :--- | :--- | :--- |
|
|
35
|
+
| **Rendering** | OS-dependent, often buggy with complex gradients. | **Pixel-perfect** across Windows, macOS, and Linux. |
|
|
36
|
+
| **Performance** | High CPU usage during rapid updates (e.g., industrial data). | **Blazing fast** with optimized native `QPainter`. |
|
|
37
|
+
| **High-DPI (4K)** | Blurry borders, broken scaling, jagged edges. | **Crisp & Sharp** automatically adapts to devicePixelRatio. |
|
|
38
|
+
| **Maintenance** | Hundreds of lines of unstructured CSS-like strings. | **Clean Python** with strongly-typed APIs and theme engines. |
|
|
39
|
+
| **PySide7/8 Future**| Style breakages requiring extensive rewrites. | **Future-proof**, seamlessly migrates to future PySide versions. |
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## ✨ Core Features
|
|
44
|
+
|
|
45
|
+
- 🚀 **Zero QSS Dependency** – Everything is drawn natively via `QPainter`.
|
|
46
|
+
- 🧩 **Quasar-Inspired Design** – Beautiful Material Design components with smooth micro-animations.
|
|
47
|
+
- 🔮 **Future-Proof API** – Built on an abstraction layer. Currently binds to `PySide6`, but fully prepared for `PySide7/8`.
|
|
48
|
+
- 🖥️ **4K / Retina Ready** – Deeply optimized for High-DPI screens. No more blurry icons or jagged lines.
|
|
49
|
+
- 🎨 **Dynamic Theme Engine** – Native Light/Dark mode support. Automatic high-contrast text calculation.
|
|
50
|
+
- 🛡️ **Enterprise-Grade Typed** – 100% Type hints. Perfect for PyCharm/VSCode intellisense and strict CI pipelines.
|
|
51
|
+
- 📦 **Lightweight & Packable** – No WebViews, no heavy assets. Very friendly for `PyInstaller`.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 📦 Installation
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install pyside-quasar
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Dependencies:**
|
|
62
|
+
- `PySide6 >= 6.6.0`
|
|
63
|
+
- `typing-extensions`
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 🚀 Quick Start
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
import sys
|
|
71
|
+
from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout
|
|
72
|
+
from pyside_quasar.components import Button, Checkbox, Dialog
|
|
73
|
+
from pyside_quasar.theme import QuasarTheme
|
|
74
|
+
|
|
75
|
+
if __name__ == "__main__":
|
|
76
|
+
app = QApplication(sys.argv)
|
|
77
|
+
|
|
78
|
+
# 1. Apply Dark Theme (Native rendering)
|
|
79
|
+
QuasarTheme.apply_dark()
|
|
80
|
+
|
|
81
|
+
# 2. Create your main window
|
|
82
|
+
win = QMainWindow()
|
|
83
|
+
win.resize(800, 600)
|
|
84
|
+
win.setWindowTitle("PySide-Quasar Demo")
|
|
85
|
+
|
|
86
|
+
# 3. Use pure QPainter components
|
|
87
|
+
central = QWidget()
|
|
88
|
+
layout = QVBoxLayout(central)
|
|
89
|
+
|
|
90
|
+
btn = Button(text="Open Dialog", color="primary", size="lg")
|
|
91
|
+
chk = Checkbox(text="Enable Advanced Settings", checked=True)
|
|
92
|
+
|
|
93
|
+
layout.addWidget(btn)
|
|
94
|
+
layout.addWidget(chk)
|
|
95
|
+
win.setCentralWidget(central)
|
|
96
|
+
|
|
97
|
+
win.show()
|
|
98
|
+
sys.exit(app.exec())
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 🧩 Components Ecosystem
|
|
104
|
+
|
|
105
|
+
We are actively expanding the ecosystem. Here is the current status:
|
|
106
|
+
|
|
107
|
+
| Module | Stable Components | In Development |
|
|
108
|
+
| :--- | :--- | :--- |
|
|
109
|
+
| **Primitives** | `Button`, `Checkbox`, `Avatar`, `Badge` | `Input`, `Switch`, `Select` |
|
|
110
|
+
| **Containers** | `Dialog` | `Card`, `Tabs`, `Drawer` |
|
|
111
|
+
| **Feedback** | - | `Toast`, `Notify`, `Progress` |
|
|
112
|
+
| **Data** | - | `Table`, `Pagination` |
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 🎨 Theming System
|
|
117
|
+
|
|
118
|
+
Say goodbye to messy stylesheets. Control your entire app's look with Python.
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
from pyside_quasar.theme import QuasarTheme
|
|
122
|
+
|
|
123
|
+
# 1. Toggle Light/Dark mode
|
|
124
|
+
QuasarTheme.apply_light()
|
|
125
|
+
QuasarTheme.apply_dark()
|
|
126
|
+
|
|
127
|
+
# 2. Set your enterprise brand color
|
|
128
|
+
QuasarTheme.set_brand_color("#1976D2")
|
|
129
|
+
|
|
130
|
+
# 3. Global border radius configuration
|
|
131
|
+
QuasarTheme.set_border_radius(6)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 📐 Roadmap & Version Strategy
|
|
137
|
+
|
|
138
|
+
Because our package name **`pyside-quasar`** does not contain a version number, you are protected from ecosystem churn.
|
|
139
|
+
|
|
140
|
+
- **`v1.x`** – Active development, binding to **PySide6**.
|
|
141
|
+
- **`v2.x`** – Seamless transition to **PySide7** (Zero code changes for UI layers).
|
|
142
|
+
- **`v3.x`** – Future-ready for **PySide8**.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## 🤝 Contributing
|
|
147
|
+
|
|
148
|
+
We welcome contributions from the global community! Whether it's a bug report, a new component, or a documentation fix, your help is appreciated.
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# Clone the repository
|
|
152
|
+
git clone https://github.com/eagleye-china/pyside-quasar.git
|
|
153
|
+
cd pyside-quasar
|
|
154
|
+
|
|
155
|
+
# Install in editable mode for development
|
|
156
|
+
pip install -e .
|
|
157
|
+
|
|
158
|
+
# Build the package
|
|
159
|
+
python -m build
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
If you find this project useful, please consider giving it a ⭐️ on GitHub! It means a lot to us.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## 📜 License
|
|
167
|
+
|
|
168
|
+
MIT License. Commercial use is allowed. See the [LICENSE](LICENSE) file for details.
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.2", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pyside-quasar"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "The Quasar Framework for PySide — Material Design components, pure QPainter, zero QSS."
|
|
9
|
+
readme = { file = "README.md", content-type = "text/markdown" }
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [
|
|
14
|
+
{ name = "eagleye-china", email = "zdt168@sina.cn" },
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
keywords = [
|
|
18
|
+
"pyside6", "qt6", "material-design", "quasar",
|
|
19
|
+
"ui-framework", "desktop", "qpainter", "pyside"
|
|
20
|
+
]
|
|
21
|
+
classifiers = [
|
|
22
|
+
"Development Status :: 4 - Beta", # 建议从 Alpha 改为 Beta,更显成熟
|
|
23
|
+
"Environment :: X11 Applications :: Qt",
|
|
24
|
+
"Environment :: Win32 (MS Windows)",
|
|
25
|
+
"Environment :: MacOS X",
|
|
26
|
+
"Intended Audience :: Developers",
|
|
27
|
+
"Operating System :: OS Independent",
|
|
28
|
+
"Programming Language :: Python :: 3.10",
|
|
29
|
+
"Programming Language :: Python :: 3.11",
|
|
30
|
+
"Programming Language :: Python :: 3.12",
|
|
31
|
+
"Programming Language :: Python :: 3.13",
|
|
32
|
+
"Topic :: Software Development :: User Interfaces",
|
|
33
|
+
"Topic :: Desktop Environment",
|
|
34
|
+
"Typing :: Typed",
|
|
35
|
+
]
|
|
36
|
+
dependencies = [
|
|
37
|
+
"PySide6>=6.6",
|
|
38
|
+
"typing-extensions>=4.0; python_version<'3.13'",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[project.optional-dependencies]
|
|
42
|
+
test = [
|
|
43
|
+
"pytest>=7.4",
|
|
44
|
+
"pytest-qt>=4.2",
|
|
45
|
+
"pytest-cov>=4.1",
|
|
46
|
+
]
|
|
47
|
+
lint = [
|
|
48
|
+
"mypy>=1.5",
|
|
49
|
+
"ruff>=0.7.0",
|
|
50
|
+
"pre-commit>=3.4",
|
|
51
|
+
"import-linter>=2.0",
|
|
52
|
+
]
|
|
53
|
+
docs = [
|
|
54
|
+
"mkdocs-material>=9.4",
|
|
55
|
+
"mkdocstrings[python]>=0.24",
|
|
56
|
+
"mkdocs-gen-files>=0.5",
|
|
57
|
+
]
|
|
58
|
+
build = [
|
|
59
|
+
"nuitka>=2.4",
|
|
60
|
+
]
|
|
61
|
+
dev = [
|
|
62
|
+
"pyside-quasar[test,lint,docs,build]",
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
[project.urls]
|
|
66
|
+
Homepage = "https://github.com/eagleye-china/pyside-quasar"
|
|
67
|
+
Documentation = "https://eagleye-china.github.io/pyside-quasar"
|
|
68
|
+
Repository = "https://github.com/eagleye-china/pyside-quasar"
|
|
69
|
+
Issues = "https://github.com/eagleye-china/pyside-quasar/issues"
|
|
70
|
+
Changelog = "https://github.com/eagleye-china/pyside-quasar/blob/main/CHANGELOG.md" # 注意:现在 GitHub 默认分支多为 master
|
|
71
|
+
|
|
72
|
+
# ================= src-layout 打包配置 =================
|
|
73
|
+
[tool.setuptools]
|
|
74
|
+
package-dir = { "" = "src" }
|
|
75
|
+
include-package-data = true
|
|
76
|
+
|
|
77
|
+
[tool.setuptools.packages.find]
|
|
78
|
+
where = ["src"]
|
|
79
|
+
# ✅ 核心修复:这里必须改成 pyside_quasar
|
|
80
|
+
include = ["pyside_quasar*"]
|
|
81
|
+
exclude = ["tests*", "examples*", "docs*", "scripts*"]
|
|
82
|
+
|
|
83
|
+
[tool.setuptools.package-data]
|
|
84
|
+
# ✅ 核心修复:这里也必须是 pyside_quasar
|
|
85
|
+
pyside_quasar = [
|
|
86
|
+
"py.typed",
|
|
87
|
+
"assets/icons/*.svg",
|
|
88
|
+
"assets/fonts/*.ttf",
|
|
89
|
+
"core/i18n/locales/*.json",
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
# ================= ruff 代码检查 & 格式化 =================
|
|
93
|
+
[tool.ruff]
|
|
94
|
+
line-length = 100
|
|
95
|
+
target-version = "py310"
|
|
96
|
+
src = ["src", "tests", "examples", "scripts"]
|
|
97
|
+
|
|
98
|
+
[tool.ruff.lint]
|
|
99
|
+
select = ["E", "F", "I", "N", "W", "UP", "B", "C4", "SIM"]
|
|
100
|
+
fix = true
|
|
101
|
+
|
|
102
|
+
[tool.ruff.lint.isort]
|
|
103
|
+
# ✅ 核心修复
|
|
104
|
+
known-first-party = ["pyside_quasar"]
|
|
105
|
+
|
|
106
|
+
[tool.ruff.format]
|
|
107
|
+
quote-style = "double"
|
|
108
|
+
indent-style = "space"
|
|
109
|
+
skip-magic-trailing-comma = false
|
|
110
|
+
|
|
111
|
+
# ================= mypy 类型检查 =================
|
|
112
|
+
[tool.mypy]
|
|
113
|
+
python_version = "3.10"
|
|
114
|
+
strict = true
|
|
115
|
+
warn_return_any = true
|
|
116
|
+
warn_unused_configs = true
|
|
117
|
+
ignore_missing_imports = false
|
|
118
|
+
# ✅ 核心修复
|
|
119
|
+
files = ["src/pyside_quasar"]
|
|
120
|
+
|
|
121
|
+
[[tool.mypy.overrides]]
|
|
122
|
+
module = [
|
|
123
|
+
"examples.*",
|
|
124
|
+
"scripts.*",
|
|
125
|
+
"tests.*",
|
|
126
|
+
]
|
|
127
|
+
strict = false
|
|
128
|
+
|
|
129
|
+
# ================= import-linter 分层架构约束 L0-L4 单向依赖 =================
|
|
130
|
+
[tool.importlinter]
|
|
131
|
+
# ✅ 核心修复
|
|
132
|
+
root_package = "pyside_quasar"
|
|
133
|
+
|
|
134
|
+
[[tool.importlinter.contracts.forbidden]]
|
|
135
|
+
name = "core_must_not_import_components"
|
|
136
|
+
modules = ["pyside_quasar.core*"]
|
|
137
|
+
forbidden_modules = ["pyside_quasar.components*", "pyside_quasar.layouts*", "pyside_quasar.templates*"]
|
|
138
|
+
|
|
139
|
+
[[tool.importlinter.contracts.forbidden]]
|
|
140
|
+
name = "components_must_not_import_templates"
|
|
141
|
+
modules = ["pyside_quasar.components*"]
|
|
142
|
+
forbidden_modules = ["pyside_quasar.templates*"]
|
|
143
|
+
|
|
144
|
+
[[tool.importlinter.contracts.forbidden]]
|
|
145
|
+
name = "primitives_containers_data_no_reverse"
|
|
146
|
+
modules = ["pyside_quasar.components.primitives*", "pyside_quasar.components.containers*"]
|
|
147
|
+
forbidden_modules = ["pyside_quasar.components.data*"]
|
|
148
|
+
|
|
149
|
+
# ================= pytest 测试配置 =================
|
|
150
|
+
[tool.pytest.ini_options]
|
|
151
|
+
testpaths = ["tests"]
|
|
152
|
+
addopts = "-ra --strict-markers --strict-config -W error::Warning"
|
|
153
|
+
qt_api = "pyside6"
|
|
154
|
+
markers = [
|
|
155
|
+
"unit: mark unit test",
|
|
156
|
+
"integration: mark integration test",
|
|
157
|
+
"visual: mark visual snapshot test",
|
|
158
|
+
"slow: mark slow running test",
|
|
159
|
+
]
|
|
160
|
+
filterwarnings = [
|
|
161
|
+
"ignore::DeprecationWarning:PySide6",
|
|
162
|
+
]
|
|
163
|
+
|
|
164
|
+
# ================= coverage 覆盖率 =================
|
|
165
|
+
[tool.coverage.run]
|
|
166
|
+
# ✅ 核心修复
|
|
167
|
+
source = ["src/pyside_quasar"]
|
|
168
|
+
branch = true
|
|
169
|
+
parallel = false
|
|
170
|
+
|
|
171
|
+
[tool.coverage.report]
|
|
172
|
+
fail_under = 80
|
|
173
|
+
show_missing = true
|
|
174
|
+
skip_covered = false
|
|
175
|
+
exclude_lines = [
|
|
176
|
+
"pragma: no cover",
|
|
177
|
+
"if TYPE_CHECKING:",
|
|
178
|
+
"@overload",
|
|
179
|
+
"raise NotImplementedError",
|
|
180
|
+
]
|