mvvm-framework 0.1.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.
@@ -0,0 +1,220 @@
1
+ Metadata-Version: 2.3
2
+ Name: mvvm-framework
3
+ Version: 0.1.0
4
+ Summary: A general-purpose MVVM framework based on PySide6 property system
5
+ Author: henxun
6
+ Author-email: henxun <1371490145@qq.com>
7
+ Requires-Dist: pyside6>=6.0.0
8
+ Requires-Python: >=3.12
9
+ Description-Content-Type: text/markdown
10
+
11
+ # MVVM Framework for PySide6
12
+
13
+ 一个基于 PySide6 属性系统实现的通用 QtWidgets MVVM 框架。
14
+
15
+ ## 项目结构
16
+
17
+ ```text
18
+ mvvm_framework/
19
+ ├── __init__.py # 包入口,导出核心组件
20
+ ├── core/ # 核心模块
21
+ │ ├── __init__.py
22
+ │ ├── observable.py # 可观察对象和列表
23
+ │ ├── model.py # 模型基类
24
+ │ ├── viewmodel.py # 视图模型基类
25
+ │ ├── command.py # 命令模式实现
26
+ │ └── binding.py # 数据绑定工具
27
+ ```
28
+
29
+ ## 核心组件
30
+
31
+ ### 1. ObservableObject(可观察对象)
32
+
33
+ 所有 MVVM 组件的基类,提供属性变更通知机制。
34
+
35
+ ```python
36
+ from mvvm_framework import ObservableObject
37
+
38
+ class MyObject(ObservableObject):
39
+ def __init__(self):
40
+ super().__init__()
41
+ self._value = 0
42
+
43
+ @property
44
+ def value(self) -> int:
45
+ return self._value
46
+
47
+ @value.setter
48
+ def value(self, val: int):
49
+ if self._value != val:
50
+ self._value = val
51
+ self.notify_property_changed("value")
52
+ ```
53
+
54
+ ### 2. Model(模型)
55
+
56
+ 数据模型层,包含业务逻辑和数据验证。
57
+
58
+ ```python
59
+ from mvvm_framework import Model
60
+
61
+ class Person(Model):
62
+ def __init__(self, name: str = "", age: int = 0):
63
+ super().__init__()
64
+ self._name = name
65
+ self._age = age
66
+
67
+ @property
68
+ def name(self) -> str:
69
+ return self._name
70
+
71
+ @name.setter
72
+ def name(self, value: str):
73
+ if self._name != value:
74
+ self._name = value
75
+ self.notify_property_changed("name")
76
+
77
+ def validate_name(self, value: str) -> str | None:
78
+ if not value.strip():
79
+ return "Name cannot be empty"
80
+ return None
81
+ ```
82
+
83
+ ### 3. ViewModel(视图模型)
84
+
85
+ 连接 Model 和 View 的桥梁,暴露数据和命令给视图。
86
+
87
+ ```python
88
+ from mvvm_framework import ViewModel, Command
89
+
90
+ class PersonViewModel(ViewModel[Person]):
91
+ def __init__(self, model: Person):
92
+ super().__init__(model)
93
+ self._save_command = Command(self.save, self.can_save)
94
+
95
+ @property
96
+ def name(self) -> str:
97
+ return self.model.name
98
+
99
+ @name.setter
100
+ def name(self, value: str):
101
+ if self.model.name != value:
102
+ self.model.name = value
103
+ self.notify_property_changed("name")
104
+
105
+ @property
106
+ def save_command(self) -> Command:
107
+ return self._save_command
108
+
109
+ def can_save(self) -> bool:
110
+ return self.model.name != ""
111
+
112
+ def save(self):
113
+ print(f"Saving {self.model.name}")
114
+ ```
115
+
116
+ ### 4. Command(命令)
117
+
118
+ 实现命令模式,用于处理用户操作。
119
+
120
+ ```python
121
+ from mvvm_framework import Command
122
+
123
+ # 基本命令
124
+ save_cmd = Command(
125
+ execute=lambda: print("Saved!"),
126
+ can_execute=lambda: True
127
+ )
128
+
129
+ # 带参数的命令
130
+ from mvvm_framework.core.command import ParameterizedCommand
131
+ delete_cmd = ParameterizedCommand(
132
+ execute=lambda item: print(f"Deleting {item}"),
133
+ can_execute=lambda item: item is not None
134
+ )
135
+ ```
136
+
137
+ ### 5. ObservableList(可观察列表)
138
+
139
+ 支持变更通知的列表类型。
140
+
141
+ ```python
142
+ from mvvm_framework import ObservableList
143
+
144
+ numbers = ObservableList([1, 2, 3])
145
+ numbers.itemAdded.connect(lambda idx, val: print(f"Added {val} at {idx}"))
146
+ numbers.append(4) # 触发 itemAdded 信号
147
+ ```
148
+
149
+ ### 6. Binding(数据绑定)
150
+
151
+ 简化 View 和 ViewModel 之间的绑定。
152
+
153
+ ```python
154
+ from mvvm_framework import Binding
155
+
156
+ # 双向文本绑定
157
+ Binding.bind_text(viewmodel, "name", line_edit)
158
+
159
+ # 单向标签绑定
160
+ Binding.bind_label(viewmodel, "display_name", label)
161
+
162
+ # 命令绑定
163
+ Binding.bind_command(viewmodel, "save_command", button)
164
+
165
+ # 值绑定(SpinBox/Slider)
166
+ Binding.bind_value(viewmodel, "age", spinbox)
167
+
168
+ # 选中状态绑定
169
+ Binding.bind_checked(viewmodel, "is_active", checkbox)
170
+ ```
171
+
172
+ ## 完整示例
173
+
174
+ 运行示例应用:
175
+
176
+ ```bash
177
+ python -m mvvm_framework.examples.person_view
178
+ ```
179
+
180
+ 或者在代码中使用:
181
+
182
+ ```python
183
+ import sys
184
+ from PySide6.QtWidgets import QApplication
185
+ from mvvm_framework.examples import Person, PersonViewModel, PersonView
186
+
187
+ app = QApplication(sys.argv)
188
+
189
+ # 创建 Model
190
+ person = Person(name="John", age=30, email="john@example.com")
191
+
192
+ # 创建 ViewModel
193
+ viewmodel = PersonViewModel(person)
194
+
195
+ # 创建 View
196
+ view = PersonView(viewmodel)
197
+ view.show()
198
+
199
+ sys.exit(app.exec())
200
+ ```
201
+
202
+ ## 特性
203
+
204
+ - **属性变更通知**: 自动通知 UI 更新
205
+ - **双向数据绑定**: View 和 ViewModel 自动同步
206
+ - **命令模式**: 统一的动作处理方式
207
+ - **数据验证**: 内置验证系统
208
+ - **计算属性缓存**: 优化性能
209
+ - **集合变更通知**: ObservableList 支持
210
+ - **类型提示**: 完整的类型注解支持
211
+
212
+ ## 安装依赖
213
+
214
+ ```bash
215
+ pip install PySide6
216
+ ```
217
+
218
+ ## 许可证
219
+
220
+ MIT License
@@ -0,0 +1,210 @@
1
+ # MVVM Framework for PySide6
2
+
3
+ 一个基于 PySide6 属性系统实现的通用 QtWidgets MVVM 框架。
4
+
5
+ ## 项目结构
6
+
7
+ ```text
8
+ mvvm_framework/
9
+ ├── __init__.py # 包入口,导出核心组件
10
+ ├── core/ # 核心模块
11
+ │ ├── __init__.py
12
+ │ ├── observable.py # 可观察对象和列表
13
+ │ ├── model.py # 模型基类
14
+ │ ├── viewmodel.py # 视图模型基类
15
+ │ ├── command.py # 命令模式实现
16
+ │ └── binding.py # 数据绑定工具
17
+ ```
18
+
19
+ ## 核心组件
20
+
21
+ ### 1. ObservableObject(可观察对象)
22
+
23
+ 所有 MVVM 组件的基类,提供属性变更通知机制。
24
+
25
+ ```python
26
+ from mvvm_framework import ObservableObject
27
+
28
+ class MyObject(ObservableObject):
29
+ def __init__(self):
30
+ super().__init__()
31
+ self._value = 0
32
+
33
+ @property
34
+ def value(self) -> int:
35
+ return self._value
36
+
37
+ @value.setter
38
+ def value(self, val: int):
39
+ if self._value != val:
40
+ self._value = val
41
+ self.notify_property_changed("value")
42
+ ```
43
+
44
+ ### 2. Model(模型)
45
+
46
+ 数据模型层,包含业务逻辑和数据验证。
47
+
48
+ ```python
49
+ from mvvm_framework import Model
50
+
51
+ class Person(Model):
52
+ def __init__(self, name: str = "", age: int = 0):
53
+ super().__init__()
54
+ self._name = name
55
+ self._age = age
56
+
57
+ @property
58
+ def name(self) -> str:
59
+ return self._name
60
+
61
+ @name.setter
62
+ def name(self, value: str):
63
+ if self._name != value:
64
+ self._name = value
65
+ self.notify_property_changed("name")
66
+
67
+ def validate_name(self, value: str) -> str | None:
68
+ if not value.strip():
69
+ return "Name cannot be empty"
70
+ return None
71
+ ```
72
+
73
+ ### 3. ViewModel(视图模型)
74
+
75
+ 连接 Model 和 View 的桥梁,暴露数据和命令给视图。
76
+
77
+ ```python
78
+ from mvvm_framework import ViewModel, Command
79
+
80
+ class PersonViewModel(ViewModel[Person]):
81
+ def __init__(self, model: Person):
82
+ super().__init__(model)
83
+ self._save_command = Command(self.save, self.can_save)
84
+
85
+ @property
86
+ def name(self) -> str:
87
+ return self.model.name
88
+
89
+ @name.setter
90
+ def name(self, value: str):
91
+ if self.model.name != value:
92
+ self.model.name = value
93
+ self.notify_property_changed("name")
94
+
95
+ @property
96
+ def save_command(self) -> Command:
97
+ return self._save_command
98
+
99
+ def can_save(self) -> bool:
100
+ return self.model.name != ""
101
+
102
+ def save(self):
103
+ print(f"Saving {self.model.name}")
104
+ ```
105
+
106
+ ### 4. Command(命令)
107
+
108
+ 实现命令模式,用于处理用户操作。
109
+
110
+ ```python
111
+ from mvvm_framework import Command
112
+
113
+ # 基本命令
114
+ save_cmd = Command(
115
+ execute=lambda: print("Saved!"),
116
+ can_execute=lambda: True
117
+ )
118
+
119
+ # 带参数的命令
120
+ from mvvm_framework.core.command import ParameterizedCommand
121
+ delete_cmd = ParameterizedCommand(
122
+ execute=lambda item: print(f"Deleting {item}"),
123
+ can_execute=lambda item: item is not None
124
+ )
125
+ ```
126
+
127
+ ### 5. ObservableList(可观察列表)
128
+
129
+ 支持变更通知的列表类型。
130
+
131
+ ```python
132
+ from mvvm_framework import ObservableList
133
+
134
+ numbers = ObservableList([1, 2, 3])
135
+ numbers.itemAdded.connect(lambda idx, val: print(f"Added {val} at {idx}"))
136
+ numbers.append(4) # 触发 itemAdded 信号
137
+ ```
138
+
139
+ ### 6. Binding(数据绑定)
140
+
141
+ 简化 View 和 ViewModel 之间的绑定。
142
+
143
+ ```python
144
+ from mvvm_framework import Binding
145
+
146
+ # 双向文本绑定
147
+ Binding.bind_text(viewmodel, "name", line_edit)
148
+
149
+ # 单向标签绑定
150
+ Binding.bind_label(viewmodel, "display_name", label)
151
+
152
+ # 命令绑定
153
+ Binding.bind_command(viewmodel, "save_command", button)
154
+
155
+ # 值绑定(SpinBox/Slider)
156
+ Binding.bind_value(viewmodel, "age", spinbox)
157
+
158
+ # 选中状态绑定
159
+ Binding.bind_checked(viewmodel, "is_active", checkbox)
160
+ ```
161
+
162
+ ## 完整示例
163
+
164
+ 运行示例应用:
165
+
166
+ ```bash
167
+ python -m mvvm_framework.examples.person_view
168
+ ```
169
+
170
+ 或者在代码中使用:
171
+
172
+ ```python
173
+ import sys
174
+ from PySide6.QtWidgets import QApplication
175
+ from mvvm_framework.examples import Person, PersonViewModel, PersonView
176
+
177
+ app = QApplication(sys.argv)
178
+
179
+ # 创建 Model
180
+ person = Person(name="John", age=30, email="john@example.com")
181
+
182
+ # 创建 ViewModel
183
+ viewmodel = PersonViewModel(person)
184
+
185
+ # 创建 View
186
+ view = PersonView(viewmodel)
187
+ view.show()
188
+
189
+ sys.exit(app.exec())
190
+ ```
191
+
192
+ ## 特性
193
+
194
+ - **属性变更通知**: 自动通知 UI 更新
195
+ - **双向数据绑定**: View 和 ViewModel 自动同步
196
+ - **命令模式**: 统一的动作处理方式
197
+ - **数据验证**: 内置验证系统
198
+ - **计算属性缓存**: 优化性能
199
+ - **集合变更通知**: ObservableList 支持
200
+ - **类型提示**: 完整的类型注解支持
201
+
202
+ ## 安装依赖
203
+
204
+ ```bash
205
+ pip install PySide6
206
+ ```
207
+
208
+ ## 许可证
209
+
210
+ MIT License
@@ -0,0 +1,16 @@
1
+ [project]
2
+ name = "mvvm-framework"
3
+ version = "0.1.0"
4
+ description = "A general-purpose MVVM framework based on PySide6 property system"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "henxun", email = "1371490145@qq.com" }
8
+ ]
9
+ requires-python = ">=3.12"
10
+ dependencies = [
11
+ "pyside6>=6.0.0",
12
+ ]
13
+
14
+ [build-system]
15
+ requires = ["uv_build>=0.11.12,<0.12.0"]
16
+ build-backend = "uv_build"
@@ -0,0 +1,21 @@
1
+ """
2
+ MVVM Framework for PySide6
3
+ A general-purpose MVVM framework based on PySide6 property system
4
+ """
5
+
6
+ from .core.observable import ObservableObject, ObservableList
7
+ from .core.model import Model
8
+ from .core.viewmodel import ViewModel
9
+ from .core.command import Command
10
+ from .core.binding import Binding
11
+
12
+ __all__ = [
13
+ 'ObservableObject',
14
+ 'ObservableList',
15
+ 'Model',
16
+ 'ViewModel',
17
+ 'Command',
18
+ 'Binding',
19
+ ]
20
+
21
+ __version__ = '1.0.0'
@@ -0,0 +1,18 @@
1
+ """
2
+ Core module for MVVM framework
3
+ """
4
+
5
+ from .observable import ObservableObject, ObservableList
6
+ from .model import Model
7
+ from .viewmodel import ViewModel
8
+ from .command import Command
9
+ from .binding import Binding
10
+
11
+ __all__ = [
12
+ 'ObservableObject',
13
+ 'ObservableList',
14
+ 'Model',
15
+ 'ViewModel',
16
+ 'Command',
17
+ 'Binding',
18
+ ]