yut 0.2.9__py3-none-any.whl

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.
Files changed (206) hide show
  1. yui/__init__.py +711 -0
  2. yui/images/ico/airplane.ico +0 -0
  3. yui/images/ico/calc.ico +0 -0
  4. yui/images/ico/circle_cube2.ico +0 -0
  5. yui/images/ico/dcube.ico +0 -0
  6. yui/images/ico/fap.ico +0 -0
  7. yui/images/ico/ndas.ico +0 -0
  8. yui/images/ico/ndw.ico +0 -0
  9. yui/images/png/3_.png +0 -0
  10. yui/images/png/3dots_h.png +0 -0
  11. yui/images/png/3dots_v.png +0 -0
  12. yui/images/png/3i.png +0 -0
  13. yui/images/png/4_dots.png +0 -0
  14. yui/images/png/4_square.png +0 -0
  15. yui/images/png/add_subs.png +0 -0
  16. yui/images/png/addgreen.png +0 -0
  17. yui/images/png/appicon.png +0 -0
  18. yui/images/png/ar_arrow.png +0 -0
  19. yui/images/png/ar_check.png +0 -0
  20. yui/images/png/arrow_cursor.png +0 -0
  21. yui/images/png/attach.png +0 -0
  22. yui/images/png/back.png +0 -0
  23. yui/images/png/ball.png +0 -0
  24. yui/images/png/ball2.png +0 -0
  25. yui/images/png/ball_blue.png +0 -0
  26. yui/images/png/ball_bullet.png +0 -0
  27. yui/images/png/ball_darkred.png +0 -0
  28. yui/images/png/ball_golden.png +0 -0
  29. yui/images/png/ball_green.png +0 -0
  30. yui/images/png/ball_light.png +0 -0
  31. yui/images/png/ball_red.png +0 -0
  32. yui/images/png/biz_1.png +0 -0
  33. yui/images/png/biz_2.png +0 -0
  34. yui/images/png/blue_star.png +0 -0
  35. yui/images/png/bulb.png +0 -0
  36. yui/images/png/bullet1.png +0 -0
  37. yui/images/png/bullet1_golden.png +0 -0
  38. yui/images/png/bullet2.png +0 -0
  39. yui/images/png/bullet2_golden.png +0 -0
  40. yui/images/png/bullet3.png +0 -0
  41. yui/images/png/bullet3_golden.png +0 -0
  42. yui/images/png/bullet4.png +0 -0
  43. yui/images/png/calc.png +0 -0
  44. yui/images/png/calendar.png +0 -0
  45. yui/images/png/cancel.png +0 -0
  46. yui/images/png/chart.png +0 -0
  47. yui/images/png/chart_bar.png +0 -0
  48. yui/images/png/chart_line.png +0 -0
  49. yui/images/png/chart_linebar.png +0 -0
  50. yui/images/png/chart_pie.png +0 -0
  51. yui/images/png/chat.png +0 -0
  52. yui/images/png/check.png +0 -0
  53. yui/images/png/check_sheet.png +0 -0
  54. yui/images/png/circle_cube.png +0 -0
  55. yui/images/png/circle_cube2.png +0 -0
  56. yui/images/png/clip_board.png +0 -0
  57. yui/images/png/close.png +0 -0
  58. yui/images/png/close_x.png +0 -0
  59. yui/images/png/continue.png +0 -0
  60. yui/images/png/contract.png +0 -0
  61. yui/images/png/contract_2.png +0 -0
  62. yui/images/png/cube4.png +0 -0
  63. yui/images/png/custom.png +0 -0
  64. yui/images/png/custom_care.png +0 -0
  65. yui/images/png/custom_money.png +0 -0
  66. yui/images/png/db.png +0 -0
  67. yui/images/png/dcube.png +0 -0
  68. yui/images/png/diamond.png +0 -0
  69. yui/images/png/doc.png +0 -0
  70. yui/images/png/doc2.png +0 -0
  71. yui/images/png/doc_percent.png +0 -0
  72. yui/images/png/doc_rpt.png +0 -0
  73. yui/images/png/download.png +0 -0
  74. yui/images/png/download_2.png +0 -0
  75. yui/images/png/drop.png +0 -0
  76. yui/images/png/earth.png +0 -0
  77. yui/images/png/exec_all.png +0 -0
  78. yui/images/png/execute.png +0 -0
  79. yui/images/png/export.png +0 -0
  80. yui/images/png/eye.png +0 -0
  81. yui/images/png/fangsheng.png +0 -0
  82. yui/images/png/fapicon.png +0 -0
  83. yui/images/png/filter.png +0 -0
  84. yui/images/png/fit_width.png +0 -0
  85. yui/images/png/fly_up.png +0 -0
  86. yui/images/png/forward.png +0 -0
  87. yui/images/png/func.png +0 -0
  88. yui/images/png/func_group.png +0 -0
  89. yui/images/png/func_item.png +0 -0
  90. yui/images/png/function.png +0 -0
  91. yui/images/png/gauge.png +0 -0
  92. yui/images/png/goal.png +0 -0
  93. yui/images/png/golden_star.png +0 -0
  94. yui/images/png/green_star.png +0 -0
  95. yui/images/png/grid.png +0 -0
  96. yui/images/png/grid_1.png +0 -0
  97. yui/images/png/grid_cube.png +0 -0
  98. yui/images/png/gridview.png +0 -0
  99. yui/images/png/hand.png +0 -0
  100. yui/images/png/heart.png +0 -0
  101. yui/images/png/hexstar.png +0 -0
  102. yui/images/png/home.png +0 -0
  103. yui/images/png/html.png +0 -0
  104. yui/images/png/index.png +0 -0
  105. yui/images/png/inout.png +0 -0
  106. yui/images/png/join.png +0 -0
  107. yui/images/png/key.png +0 -0
  108. yui/images/png/label.png +0 -0
  109. yui/images/png/label_2.png +0 -0
  110. yui/images/png/last.png +0 -0
  111. yui/images/png/left.png +0 -0
  112. yui/images/png/left2.png +0 -0
  113. yui/images/png/levels.png +0 -0
  114. yui/images/png/lightning.png +0 -0
  115. yui/images/png/link.png +0 -0
  116. yui/images/png/lock.png +0 -0
  117. yui/images/png/logo.png +0 -0
  118. yui/images/png/lookup.png +0 -0
  119. yui/images/png/loop.png +0 -0
  120. yui/images/png/max.png +0 -0
  121. yui/images/png/mblocks.png +0 -0
  122. yui/images/png/milestone.png +0 -0
  123. yui/images/png/min.png +0 -0
  124. yui/images/png/minus.png +0 -0
  125. yui/images/png/money_forward.png +0 -0
  126. yui/images/png/more.png +0 -0
  127. yui/images/png/multi_block.png +0 -0
  128. yui/images/png/next.png +0 -0
  129. yui/images/png/notebook.png +0 -0
  130. yui/images/png/nstc.png +0 -0
  131. yui/images/png/off.png +0 -0
  132. yui/images/png/okr.png +0 -0
  133. yui/images/png/open.png +0 -0
  134. yui/images/png/org.png +0 -0
  135. yui/images/png/org1.png +0 -0
  136. yui/images/png/org2.png +0 -0
  137. yui/images/png/outcome.png +0 -0
  138. yui/images/png/paper_plane.png +0 -0
  139. yui/images/png/parts.png +0 -0
  140. yui/images/png/pause.png +0 -0
  141. yui/images/png/pc.png +0 -0
  142. yui/images/png/pc_bar.png +0 -0
  143. yui/images/png/person_card.png +0 -0
  144. yui/images/png/person_chart.png +0 -0
  145. yui/images/png/person_doc.png +0 -0
  146. yui/images/png/person_fire.png +0 -0
  147. yui/images/png/person_hire.png +0 -0
  148. yui/images/png/pie.png +0 -0
  149. yui/images/png/pie_2.png +0 -0
  150. yui/images/png/play.png +0 -0
  151. yui/images/png/plus.png +0 -0
  152. yui/images/png/red_star.png +0 -0
  153. yui/images/png/refresh.png +0 -0
  154. yui/images/png/report.png +0 -0
  155. yui/images/png/revert.png +0 -0
  156. yui/images/png/right.png +0 -0
  157. yui/images/png/right2.png +0 -0
  158. yui/images/png/right_3.png +0 -0
  159. yui/images/png/save.png +0 -0
  160. yui/images/png/save_data.png +0 -0
  161. yui/images/png/setting.png +0 -0
  162. yui/images/png/show_normal.png +0 -0
  163. yui/images/png/site.png +0 -0
  164. yui/images/png/site_blue.png +0 -0
  165. yui/images/png/sort.png +0 -0
  166. yui/images/png/star.png +0 -0
  167. yui/images/png/stop.png +0 -0
  168. yui/images/png/sum.png +0 -0
  169. yui/images/png/sum_1.png +0 -0
  170. yui/images/png/target.png +0 -0
  171. yui/images/png/time.png +0 -0
  172. yui/images/png/to_cloud.png +0 -0
  173. yui/images/png/todo.png +0 -0
  174. yui/images/png/tools.png +0 -0
  175. yui/images/png/tree.png +0 -0
  176. yui/images/png/trush.png +0 -0
  177. yui/images/png/tumber.png +0 -0
  178. yui/images/png/turn_up.png +0 -0
  179. yui/images/png/two_persons.png +0 -0
  180. yui/images/png/user.png +0 -0
  181. yui/images/png/var.png +0 -0
  182. yui/images/png/view.png +0 -0
  183. yui/images/png/vv_down.png +0 -0
  184. yui/images/png/vvv_down.png +0 -0
  185. yui/images.qrc +189 -0
  186. yui/images_rc.py +138253 -0
  187. yui/img.py +185 -0
  188. yui/qrc_tools.py +54 -0
  189. yui/wdg.py +1651 -0
  190. yui/ydict.py +95 -0
  191. yui/yfield.py +1266 -0
  192. yui/yform.py +205 -0
  193. yui/ylookup.py +329 -0
  194. yui/ymodel.py +496 -0
  195. yui/ystat.py +1225 -0
  196. yui/ytable.py +612 -0
  197. yui/ytree.py +102 -0
  198. yus/__init__.py +163 -0
  199. yus/dbm.py +719 -0
  200. yut/__init__.py +539 -0
  201. yut/mes.py +206 -0
  202. yut/rmi.py +196 -0
  203. yut/win32.py +260 -0
  204. yut-0.2.9.dist-info/METADATA +18 -0
  205. yut-0.2.9.dist-info/RECORD +206 -0
  206. yut-0.2.9.dist-info/WHEEL +4 -0
yui/__init__.py ADDED
@@ -0,0 +1,711 @@
1
+ # -*- yui.py: python ; coding: utf-8 -*-
2
+ # 基于PySide开发的通用GUI工具
3
+ import sys
4
+ from enum import Enum
5
+
6
+ from PySide6.QtCore import Qt, Signal, QSize, QEvent
7
+ from PySide6.QtGui import (QIcon, QColor, QEnterEvent, QPalette, QPixmap, QAction)
8
+ from PySide6.QtWidgets import (QApplication, QToolBar, QWidget, QPushButton, QToolButton, QSizePolicy,
9
+ QLayout, QHBoxLayout, QVBoxLayout, QGridLayout, QFormLayout, QDateTimeEdit,
10
+ QCalendarWidget, QGroupBox, QFileDialog, QDateEdit, QMenu)
11
+ from PySide6.QtWidgets import (QMessageBox)
12
+
13
+ from yut.win32 import set_process_user_model_id
14
+ from yut import get_attr, is_execute_able, call_exp
15
+
16
+
17
+ class Theme(Enum):
18
+ DARK = '深色'
19
+ LIGHT = '浅色'
20
+
21
+ def icon_color(self):
22
+ return {self.DARK: QColor(100, 149, 237),
23
+ self.LIGHT: QColor(80, 128, 218), }.get(self)
24
+
25
+ def hover_color(self):
26
+ return {self.DARK: QColor(80, 140, 242),
27
+ self.LIGHT: QColor(80, 120, 226), }.get(self)
28
+
29
+ def hi_light_color(self):
30
+ return {self.DARK: QColor(212, 212, 212),
31
+ self.LIGHT: QColor(212, 212, 30), }.get(self)
32
+
33
+ def enforce_color(self):
34
+ return {self.DARK: QColor(192, 168, 32),
35
+ self.LIGHT: QColor(16, 12, 30), }.get(self)
36
+
37
+
38
+ class HoveredButton(QPushButton):
39
+ entered = Signal()
40
+ leaved = Signal()
41
+
42
+ def enterEvent(self, event: QEnterEvent) -> None:
43
+ super().enterEvent(event)
44
+ self.entered.emit()
45
+
46
+ def leaveEvent(self, event: QEvent) -> None:
47
+ super().leaveEvent(event)
48
+ self.leaved.emit()
49
+
50
+
51
+ class HoveredToolButton(QToolButton):
52
+ entered = Signal()
53
+ leaved = Signal()
54
+
55
+ def enterEvent(self, event: QEnterEvent) -> None:
56
+ super().enterEvent(event)
57
+ self.entered.emit()
58
+
59
+ def leaveEvent(self, event: QEvent) -> None:
60
+ super().leaveEvent(event)
61
+ self.leaved.emit()
62
+
63
+
64
+ current_theme = Theme.DARK
65
+
66
+
67
+ def set_current_theme(theme: Theme):
68
+ global current_theme
69
+ current_theme = theme
70
+
71
+
72
+ def create_default_app(argv=None, theme: Theme = Theme.DARK, app_name=None, icon_file=None) -> QApplication:
73
+ import yui.images_rc as images
74
+ import qtmodern.styles as style
75
+ arv = argv if argv is not None else sys.argv
76
+ app = QApplication(arv)
77
+ if app_name:
78
+ set_process_user_model_id(app_name)
79
+ app.setApplicationDisplayName(app_name)
80
+ app.setApplicationName(app_name)
81
+ if icon_file:
82
+ app.setWindowIcon(load_icon(icon_file, colored=False))
83
+ set_current_theme(theme)
84
+ if theme == Theme.DARK:
85
+ style.dark(app)
86
+ else:
87
+ style.light(app)
88
+ return app
89
+
90
+
91
+ def get_app() -> QApplication | None:
92
+ return QApplication.instance()
93
+
94
+
95
+ def get_mainwindow() -> QWidget | None:
96
+ app = get_app()
97
+ if hasattr(app, 'main_window'):
98
+ return app.main_window
99
+ else:
100
+ return app.activeWindow()
101
+
102
+
103
+ def get_active_window() -> QWidget | None:
104
+ app = get_app()
105
+ return app.activeWindow() if app else None
106
+
107
+
108
+ def colored_pixmap(file_name, colored=True):
109
+ pix = QPixmap(file_name)
110
+ if colored:
111
+ mask = pix.createMaskFromColor(Qt.GlobalColor.transparent)
112
+ color = current_theme.icon_color() # QPalette().color(QPalette.Highlight) # theme_icon_color
113
+ pix.fill(color)
114
+ pix.setMask(mask)
115
+ return pix
116
+
117
+
118
+ def load_icon(file_name, colored=True):
119
+ return QIcon(colored_pixmap(file_name, colored=colored))
120
+
121
+
122
+ def create_action(text, trigger, icon_file=None, parent=None, object_name=None) -> QAction:
123
+ action = QAction(load_icon(icon_file), text, parent)
124
+ action.triggered.connect(trigger)
125
+ action.setObjectName(object_name)
126
+ return action
127
+
128
+
129
+ def create_button(text='', trigger=None, icon=None, icon_file=None, flat=None, tip_text=None, parent=None,
130
+ object_name=None, icon_only=False,
131
+ icon_size: QSize | int = None, ):
132
+ btn = QPushButton(text if not icon_only else '', parent=parent)
133
+ btn.setObjectName(object_name)
134
+ if icon:
135
+ btn.setIcon(icon)
136
+ else:
137
+ if icon_file:
138
+ btn.setIcon(load_icon(icon_file))
139
+ if flat is not None:
140
+ btn.setFlat(flat)
141
+ if tip_text is not None:
142
+ btn.setToolTip(tip_text)
143
+ else:
144
+ if text:
145
+ btn.setToolTip(text)
146
+ if trigger:
147
+ btn.clicked.connect(trigger)
148
+ if icon_size:
149
+ size = icon_size if isinstance(icon_size, QSize) else QSize(icon_size, icon_size)
150
+ btn.setIconSize(size)
151
+ btn.setIconSize(QSize(icon_size, icon_size))
152
+ return btn
153
+
154
+
155
+ def create_tool_button(text='', trigger=None, icon=None, icon_file=None, tip_text=None, parent=None,
156
+ icon_size: QSize | int = None,
157
+ flat=False, object_name=None) -> QToolButton:
158
+ btn = QToolButton(parent=parent)
159
+ btn.setObjectName(object_name)
160
+ if text:
161
+ btn.setText(text)
162
+ if icon:
163
+ btn.setIcon(icon)
164
+ else:
165
+ if icon_file:
166
+ btn.setIcon(load_icon(icon_file))
167
+ if tip_text is not None:
168
+ btn.setToolTip(tip_text)
169
+ else:
170
+ if text:
171
+ btn.setToolTip(text)
172
+ if trigger:
173
+ btn.clicked.connect(trigger)
174
+ if icon_size:
175
+ size = icon_size if isinstance(icon_size, QSize) else QSize(icon_size, icon_size)
176
+ btn.setIconSize(size)
177
+ if flat:
178
+ btn.setStyleSheet("border - style: flat; background: transparent;")
179
+ # btn.setFocusPolicy(Qt.FocusPolicy.NoFocus)
180
+ return btn
181
+
182
+
183
+ def create_menu_button(menu: QMenu,
184
+ title=None,
185
+ icon_file=None,
186
+ icon=None,
187
+ hovered=False,
188
+ icon_size: QSize | int = None,
189
+ tool_button=False,
190
+ indicator=False,
191
+ object_name=None) -> HoveredButton | HoveredToolButton | QToolButton | QPushButton:
192
+ if icon_size is not None:
193
+ size = icon_size if isinstance(icon_size, QSize) else QSize(icon_size, icon_size)
194
+ else:
195
+ size = QSize(14, 14)
196
+
197
+ if hovered:
198
+ if tool_button:
199
+ btn = HoveredToolButton()
200
+ btn.setSizePolicy(QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed))
201
+ btn.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
202
+ else:
203
+ btn = HoveredButton()
204
+ btn.setFlat(True)
205
+ btn.entered.connect(btn.click)
206
+ else:
207
+ if tool_button:
208
+ btn = QToolButton()
209
+ btn.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
210
+ else:
211
+ btn = QPushButton()
212
+ btn.setFlat(True)
213
+
214
+ btn.setSizePolicy(QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed))
215
+
216
+ if not indicator: # 去掉menu指引箭头
217
+ if isinstance(btn, QToolButton):
218
+ btn.setStyleSheet('QToolButton::menu-indicator {image: none;}')
219
+ if isinstance(btn, QPushButton):
220
+ btn.setStyleSheet('QPushButton::menu-indicator {image: none;}')
221
+
222
+ btn.setMenu(menu)
223
+ btn.setIconSize(size)
224
+ btn.setObjectName(object_name)
225
+
226
+ if title:
227
+ btn.setText(title)
228
+ btn.setToolTip(title)
229
+
230
+ if icon:
231
+ btn.setIcon(icon)
232
+ elif icon_file:
233
+ btn.setIcon(load_icon(icon_file))
234
+
235
+ return btn
236
+
237
+
238
+ def create_toolbar(buttons=None, actions=None, icon_size=12, parent=None, object_name=None) -> QToolBar:
239
+ tbar = QToolBar(parent=parent)
240
+ tbar.setIconSize(QSize(icon_size, icon_size))
241
+ tbar.setObjectName(object_name)
242
+ if actions:
243
+ tbar.addActions(actions)
244
+ if buttons:
245
+ if actions:
246
+ tbar.addSeparator()
247
+ for btn in buttons:
248
+ tbar.addWidget(btn)
249
+ return tbar
250
+
251
+
252
+ def pop_info(*args, title=None, sep=' '):
253
+ text = sep.join([str(a) for a in args])
254
+ if not title:
255
+ title = '提示信息'
256
+ QMessageBox.information(get_mainwindow(), title, text)
257
+
258
+
259
+ def pop_question(*args, title=None, sep=' '):
260
+ text = sep.join([str(a) for a in args])
261
+ if not title:
262
+ title = '请确认信息'
263
+ return QMessageBox.question(get_mainwindow(), title, text,
264
+ QMessageBox.StandardButton.Ok,
265
+ QMessageBox.StandardButton.Cancel) == QMessageBox.StandardButton.Ok
266
+
267
+
268
+ def pop_warning(*args, title=None, sep=' '):
269
+ text = sep.join([str(a) for a in args])
270
+ if not title:
271
+ title = '提示信息'
272
+ QMessageBox.warning(get_mainwindow(), title, text)
273
+
274
+
275
+ def load_style_sheet(fname):
276
+ style = ''
277
+ for line in open(fname, encoding='utf-8').readlines():
278
+ style += line
279
+ get_app().setStyleSheet(style)
280
+
281
+
282
+ def contrast_color(color):
283
+ luminance = (0.299 * color.red() + 0.587 * color.green() + 0.114 * color.blue()) / 255
284
+ # luminance = (color.red() + color.green() + color.blue()) / (3 * 255)
285
+ if luminance > 0.5:
286
+ contrast = QColor('#000000')
287
+ else:
288
+ contrast = QColor('#FFFFFF')
289
+ return contrast
290
+
291
+
292
+ def change_font(w, bold=None, size=None, italic=None, underline=None, strike=None):
293
+ font = w.font()
294
+ if bold is not None:
295
+ font.setBold(bold)
296
+ if underline is not None:
297
+ font.setUnderline(underline)
298
+ if italic is not None:
299
+ font.setItalic(italic)
300
+ if strike is not None:
301
+ font.setStrike(strike)
302
+ if size:
303
+ font.setPointSize(size)
304
+ w.setFont(font)
305
+ return w
306
+
307
+
308
+ def change_item_display(item, bold=None, italic=None, underline=None, strike=None, size=None, color=None,
309
+ background=None):
310
+ font = item.font()
311
+ if bold is not None:
312
+ font.setBold(bold)
313
+ if size:
314
+ font.setPointSize(size)
315
+ if underline is not None:
316
+ font.setUnderline(underline)
317
+ if italic is not None:
318
+ font.setItalic(italic)
319
+ if strike is not None:
320
+ font.setStrike(strike)
321
+ item.setFont(font)
322
+
323
+ if color:
324
+ item.setForeground(color)
325
+ if background:
326
+ item.setBackground(background)
327
+ return item
328
+
329
+
330
+ def set_label_color(lb, bk_color=None, fore_color=None):
331
+ pe = QPalette()
332
+ if bk_color:
333
+ lb.setAutoFillBackground(True)
334
+ pe.setColor(QPalette.ColorRole.Window, bk_color)
335
+ if fore_color:
336
+ pe.setColor(QPalette.ColorRole.WindowText, fore_color)
337
+ lb.setPalette(pe)
338
+ return lb
339
+
340
+
341
+ def set_widget_color(wdg, bk_color=None, fore_color=None):
342
+ palette = wdg.palette()
343
+ if bk_color:
344
+ palette.setColor(QPalette.ColorRole.Window, bk_color)
345
+ if fore_color:
346
+ palette.setColor(QPalette.ColorRole.Text, fore_color)
347
+ wdg.setPalette(palette)
348
+
349
+
350
+ def create_layout(layout_flag='H', parent=None,
351
+ object_name=None) -> QHBoxLayout | QVBoxLayout | QGridLayout | QFormLayout:
352
+ """
353
+ 依据标记创建布局对象
354
+ :param object_name:
355
+ :param parent:
356
+ :param layout_flag:
357
+ 'H' - HBox ;
358
+ 'V' - VBox ;
359
+ 'F' - FormLayout ;
360
+ 'G##' - GridLayout 紧跟在G后面的是Grid布局的列数目,如'G3'表示创建表格布局,每行3列,会将列数加到布局回想的column_num属性中
361
+ :return: QLayout 对象,如果是GridLayout,增加column_num属性,保存打算布置的列数
362
+ """
363
+ if layout_flag == 'V':
364
+ lyt = QVBoxLayout()
365
+ lyt.setAlignment(Qt.AlignmentFlag.AlignLeft)
366
+ lyt.setSpacing(4)
367
+ elif layout_flag.startswith('G'):
368
+ lyt = QGridLayout()
369
+ if len(layout_flag) > 1:
370
+ lyt.column_num = int(layout_flag[1:])
371
+ lyt.setHorizontalSpacing(4)
372
+ lyt.setVerticalSpacing(4)
373
+ elif layout_flag == 'F':
374
+ lyt = QFormLayout()
375
+ lyt.setAlignment(Qt.AlignmentFlag.AlignTop)
376
+ lyt.setLabelAlignment(
377
+ Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTrailing | Qt.AlignmentFlag.AlignVCenter)
378
+ lyt.setFormAlignment(Qt.AlignmentFlag.AlignLeading | Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
379
+ lyt.setHorizontalSpacing(16)
380
+ lyt.setVerticalSpacing(16)
381
+ else:
382
+ lyt = QHBoxLayout()
383
+ lyt.setAlignment(Qt.AlignmentFlag.AlignVCenter)
384
+ lyt.setSpacing(4)
385
+ lyt.setContentsMargins(0, 0, 0, 0)
386
+ lyt.setParent(parent)
387
+ lyt.setObjectName(object_name)
388
+ return lyt
389
+
390
+
391
+ def create_widget(target=QWidget, parent=None, object_name=None) -> QWidget:
392
+ """
393
+ 创建QWidget
394
+ :param object_name:
395
+ :param target: 可以是QWidget实例/QWidget class及其子类/函数/表达式,默认为QWidget class
396
+ :param parent:
397
+ :return:
398
+ """
399
+ import inspect
400
+ widget = None
401
+ if isinstance(target, QWidget):
402
+ widget = target
403
+ elif inspect.isclass(target):
404
+ widget = target(parent=parent)
405
+ elif is_execute_able(target):
406
+ widget = target()
407
+ elif isinstance(target, str):
408
+ widget = call_exp(target)
409
+ if parent and widget:
410
+ widget.setParent(parent)
411
+ widget.setObjectName(object_name)
412
+ return widget
413
+
414
+
415
+ def create_layout_widget(target=QWidget, parent=None, layout_flag='H', object_name=None, window_title=None) -> QWidget:
416
+ """
417
+ 创建带布局的widget,并将布局设置为widget的主布局
418
+ :param target: Widget类,默认使用QWidget
419
+ :param layout_flag:
420
+ 'H' - HBox ;
421
+ 'V' - VBox ;
422
+ 'F' - FormLayout ;
423
+ 'G##' - GridLayout 紧跟在G后面的是Grid布局的列数目,如'G3'表示创建表格布局,每行3列,会将列数加到布局回想的column_num属性中
424
+ :param parent: 创建widget时使用的父对象
425
+ :param object_name: 对象名,setObjectName
426
+ :param window_title: 窗口标题,setWindowTitle
427
+ :return: QWidget
428
+ """
429
+ widget = create_widget(target, parent=parent)
430
+ widget.setLayout(create_layout(layout_flag))
431
+ widget.setObjectName(object_name)
432
+ if window_title:
433
+ widget.setWindowTitle(window_title)
434
+ return widget
435
+
436
+
437
+ def set_layout_spacing(lyt, h_spacing=0, v_spacing=0):
438
+ if isinstance(lyt, QHBoxLayout):
439
+ lyt.setSpacing(h_spacing)
440
+ elif isinstance(lyt, QVBoxLayout):
441
+ lyt.setSpacing(v_spacing)
442
+ elif isinstance(lyt, QGridLayout):
443
+ lyt.setHorizontalSpacing(h_spacing)
444
+ lyt.setVerticalSpacing(v_spacing)
445
+ elif isinstance(lyt, QFormLayout):
446
+ lyt.setHorizontalSpacing(h_spacing)
447
+ lyt.setVerticalSpacing(v_spacing)
448
+
449
+
450
+ def clear_layout(layout: QLayout):
451
+ for i in range(layout.count() - 1, -1, -1):
452
+ item = layout.itemAt(i)
453
+ if item.widget():
454
+ item.widget().deleteLater()
455
+ layout.removeItem(item)
456
+
457
+
458
+ def show_in_center(widget):
459
+ screen_rect = get_app().primaryScreen().geometry()
460
+ widget.setGeometry(screen_rect.width() // 2 - widget.width() // 2,
461
+ screen_rect.height() // 2 - widget.height() // 2,
462
+ widget.width(),
463
+ widget.height())
464
+ widget.show()
465
+
466
+
467
+ def create_date_edit(date, parent=None, object_name=None) -> QDateEdit:
468
+ edt = QDateTimeEdit(date, parent=parent)
469
+ edt.setObjectName(object_name)
470
+ edt.setCalendarPopup(True)
471
+ edt.setDisplayFormat('yyyy-MM-dd')
472
+ edt.setMinimumWidth(100)
473
+ w = QCalendarWidget(edt)
474
+ w.setGridVisible(True)
475
+ w.setAutoFillBackground(True)
476
+ w.setObjectName('dateEditCalendar')
477
+ w.setMinimumWidth(200)
478
+ w.setMaximumHeight(300)
479
+ edt._cal_widget = w
480
+ edt.setCalendarWidget(edt._cal_widget)
481
+ return edt
482
+
483
+
484
+ def filename_for_save(path='.', caption=None, file_filter='*.*'):
485
+ caption = caption if not caption else '请选择待保存的文件位置'
486
+ dlg = QFileDialog(parent=None, caption=caption)
487
+ files = dlg.getSaveFileName(parent=None, caption=caption, dir=path, filter=file_filter)
488
+ if files[0]:
489
+ return files[0]
490
+ else:
491
+ return None
492
+
493
+
494
+ def add_to_layout(layout: QLayout, widget: QWidget | QLayout, index=-1):
495
+ if index < 0:
496
+ attr = 'addWidget' if isinstance(widget, QWidget) else 'addLayout'
497
+ else:
498
+ attr = 'insertWidget' if isinstance(widget, QWidget) else 'insertLayout'
499
+ fn_add = get_attr(layout, attr)
500
+ if isinstance(layout, QGridLayout): # Grid布局
501
+ n_count = layout.count()
502
+ if hasattr(layout, 'column_num'):
503
+ column_num = get_attr(layout, 'column_num', 2)
504
+ fn_add(widget, n_count / column_num, n_count % column_num)
505
+ else: # HBox | VBox |GroupBox
506
+ if index < 0:
507
+ fn_add(widget)
508
+ else:
509
+ fn_add(index, widget)
510
+
511
+
512
+ def add_field(layout: QLayout, field: QWidget, label=None, index=-1):
513
+ """
514
+ 在布局中添加部件。如果是FormLayout,要求label为QWidget使用addRow
515
+ :param index: -1 - add; >=0 - insert
516
+ :param layout:
517
+ :param field:
518
+ :param label:
519
+ :return:
520
+ """
521
+ if isinstance(layout, QFormLayout): # Form布局
522
+ layout.addRow(label, field)
523
+ else:
524
+ w = field
525
+ if label is not None: # 创建组合框,否则直接在layout中增加
526
+ g_box = QGroupBox(field.parent())
527
+ g_box.setLayout(QVBoxLayout())
528
+ g_box.layout().setContentsMargins(0, 0, 0, 0)
529
+ g_box.layout().addWidget(field)
530
+ g_box.setTitle(label)
531
+ w = g_box
532
+ add_to_layout(layout, w, index)
533
+
534
+
535
+ class UnitToken:
536
+ """
537
+ 字段单元代表符号
538
+ 不要声明为枚举类型,方便json传递时直接使用字面量名称
539
+ """
540
+ TEXT = '*' # 文本
541
+ SWITCH = '!' # 开关
542
+ NUMBER = '.' # 小数
543
+ CURRENCY = '$' # 金额
544
+ INT = '#' # 整数
545
+ DATE = 'd' # 日期
546
+ TIME = 't' # 日期时间
547
+ YEAR = 'y' # 年份
548
+ YEAR_MONTH = 'm' # 年月
549
+ CHOOSE = '@' # 字典或码表选择
550
+ LOOKUP = '?' # 对照映射
551
+ PERCENT = '%' # 百分比
552
+ CLOCK = 'cl' # 时刻
553
+ RICH_TEXT = 'rt' # 长文本
554
+
555
+
556
+ class UnitType(Enum):
557
+ TEXT = '*' # 文本
558
+ SWITCH = '!' # 开关
559
+ NUMBER = '.' # 小数
560
+ CURRENCY = '$' # 金额
561
+ INT = '#' # 整数
562
+ DATE = 'd' # 日期
563
+ TIME = 't' # 日期时间
564
+ YEAR = 'y' # 年份
565
+ YEAR_MONTH = 'm' # 年月
566
+ CHOOSE = '@' # 字典或码表选择
567
+ LOOKUP = '?' # 对照映射
568
+ PERCENT = '%' # 百分比
569
+ CLOCK = 'cl' # 时刻
570
+ RICH_TEXT = 'rt' # 长文本
571
+
572
+
573
+ class ChooseFlag:
574
+ """
575
+ 选择单元的具体选取模式
576
+ 不要声明为枚举类型,方便json传递时直接使用字面量名称
577
+ """
578
+ LIST = 0
579
+ RADIO = 1
580
+ CHECK = 2
581
+
582
+
583
+ class AttitudeToken:
584
+ """
585
+ 显示调性
586
+ """
587
+ NEGATIVE = '--' # 阴性: 消极/反向/负面/异常/出错
588
+ WEAK_NEGATIVE = '-' # 弱阴 - 预警
589
+ NEUTRAL = '=' # 中性
590
+ WEAK_POSITIVE = '+' # 弱阳
591
+ POSITIVE = '++' # 阳性: 积极/正向/正面/正常/无差错
592
+ INACTIVE = '~' # 失能:处于无效/失效状态
593
+
594
+
595
+ class WorkMode(Enum):
596
+ """
597
+ 单元的工作模式,显示/编辑
598
+ """
599
+ DISPLAY = 0 # 显示模式
600
+ EDIT = 1 # 编辑模式
601
+ WATCH = 2 # 监视模式 - 只读显示,但该字段在其它地方改变之后需要更新
602
+
603
+
604
+ class EditMode(Enum):
605
+ """
606
+ 表单/列表的编辑模式,新增/修改
607
+ """
608
+ NEW = 0 # 新增
609
+ MODIFY = 1 # 修改
610
+
611
+
612
+ class Stage(Enum):
613
+ """
614
+ 单元的使用场景
615
+ """
616
+ IN_FORM = 0 # 表单式
617
+ IN_TABLE = 1 # 列表式
618
+ IN_QUERY = 2 # 查询条件
619
+
620
+
621
+ class ChooseMode(Enum):
622
+ """
623
+ 选择单元的具体选取模式
624
+ """
625
+ LIST = 0
626
+ RADIO = 1
627
+ CHECK = 2
628
+
629
+
630
+ class TranslateDirection(Enum):
631
+ TO_TEXT = 0 # 值 -> 显示文字
632
+ TO_VALUE = 1 # 显示文字 -> 值
633
+
634
+
635
+ class LookupViewType(Enum):
636
+ """
637
+ LookupView类型
638
+ """
639
+ List = 0 # 列表: 无表头,无查询条件,可以筛选
640
+ Table = 1 # 表格: 有表头,可以多列,可以带查询条件以及点击排序
641
+ Tree = 2 # 树:有表头,可以多列,树形展开,无查询条件录入框
642
+
643
+
644
+ class DisplayAttitude(Enum):
645
+ """
646
+ 显示调性,可根据
647
+ """
648
+ NEGATIVE = '--' # 阴性: 消极/反向/负面/异常/出错
649
+ WEAK_NEGATIVE = '-' # 弱阴 - 预警
650
+ NEUTRAL = '=' # 中性
651
+ WEAK_POSITIVE = '+' # 弱阳
652
+ POSITIVE = '++' # 阳性: 积极/正向/正面/正常/无差错
653
+ INACTIVE = '~' # 失能:处于无效/失效状态
654
+
655
+
656
+ class QueryOp(Enum):
657
+ EQU = '='
658
+ GE = '>=' # >=
659
+ GT = '>' # >
660
+ LE = '<=' # <=
661
+ LT = '<' # <
662
+ NEQ = '!=' # !=
663
+ BETWEEN = '~'
664
+ IN = '@'
665
+ NOT_IN = '!@' # not in
666
+ LIKE = '*'
667
+ NOT_LIKE = '!*' # not like
668
+ LIKE_IN = '**' # like A or like B or like C ...
669
+
670
+ def text(self):
671
+ return {
672
+ self.EQU: '等于',
673
+ self.GE: '不低于',
674
+ self.GT: '高于',
675
+ self.LE: '不高于',
676
+ self.LT: '小于',
677
+ self.NEQ: '不等于',
678
+ self.BETWEEN: '范围',
679
+ self.IN: '属于',
680
+ self.NOT_IN: '不属于',
681
+ self.LIKE: '匹配',
682
+ self.NOT_LIKE: '不匹配',
683
+ self.LIKE_IN: '用"|"分隔的多值匹配',
684
+ }.get(self)
685
+
686
+
687
+ def alignment_flag(tag):
688
+ """
689
+ :param tag:
690
+ '>' - 右对齐
691
+ '|' - 水平居中
692
+ '<' - 左对齐
693
+ '^' - 顶对齐
694
+ '-' - 垂直居中
695
+ '_' - 底对齐
696
+ :return:
697
+ """
698
+ horizontal_alignment, vertical_alignment = Qt.AlignmentFlag.AlignCenter, Qt.AlignmentFlag.AlignVCenter
699
+ for ch, h_flag in {'>': Qt.AlignmentFlag.AlignRight,
700
+ '<': Qt.AlignmentFlag.AlignLeft,
701
+ '|': Qt.AlignmentFlag.AlignCenter
702
+ }.items():
703
+ if ch in tag:
704
+ horizontal_alignment = h_flag
705
+ for ch, v_flag in {'^': Qt.AlignmentFlag.AlignTop,
706
+ '_': Qt.AlignmentFlag.AlignBottom,
707
+ '-': Qt.AlignmentFlag.AlignVCenter
708
+ }.items():
709
+ if ch in tag:
710
+ vertical_alignment = v_flag
711
+ return horizontal_alignment | vertical_alignment
Binary file
Binary file
Binary file