yut 0.2.20__py2.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.
- yui/__init__.py +608 -0
- yui/images/ico/airplane.ico +0 -0
- yui/images/ico/calc.ico +0 -0
- yui/images/ico/circle_cube2.ico +0 -0
- yui/images/ico/dcube.ico +0 -0
- yui/images/ico/fap.ico +0 -0
- yui/images/ico/ndas.ico +0 -0
- yui/images/ico/ndw.ico +0 -0
- yui/images/png/3_.png +0 -0
- yui/images/png/3dots_h.png +0 -0
- yui/images/png/3dots_v.png +0 -0
- yui/images/png/3i.png +0 -0
- yui/images/png/4_dots.png +0 -0
- yui/images/png/4_square.png +0 -0
- yui/images/png/add_subs.png +0 -0
- yui/images/png/addgreen.png +0 -0
- yui/images/png/appicon.png +0 -0
- yui/images/png/ar_arrow.png +0 -0
- yui/images/png/ar_check.png +0 -0
- yui/images/png/arrow_cursor.png +0 -0
- yui/images/png/attach.png +0 -0
- yui/images/png/back.png +0 -0
- yui/images/png/ball.png +0 -0
- yui/images/png/ball2.png +0 -0
- yui/images/png/ball_blue.png +0 -0
- yui/images/png/ball_bullet.png +0 -0
- yui/images/png/ball_darkred.png +0 -0
- yui/images/png/ball_golden.png +0 -0
- yui/images/png/ball_green.png +0 -0
- yui/images/png/ball_light.png +0 -0
- yui/images/png/ball_red.png +0 -0
- yui/images/png/biz_1.png +0 -0
- yui/images/png/biz_2.png +0 -0
- yui/images/png/blue_star.png +0 -0
- yui/images/png/bulb.png +0 -0
- yui/images/png/bullet1.png +0 -0
- yui/images/png/bullet1_golden.png +0 -0
- yui/images/png/bullet2.png +0 -0
- yui/images/png/bullet2_golden.png +0 -0
- yui/images/png/bullet3.png +0 -0
- yui/images/png/bullet3_golden.png +0 -0
- yui/images/png/bullet4.png +0 -0
- yui/images/png/calc.png +0 -0
- yui/images/png/calendar.png +0 -0
- yui/images/png/cancel.png +0 -0
- yui/images/png/chart.png +0 -0
- yui/images/png/chart_bar.png +0 -0
- yui/images/png/chart_line.png +0 -0
- yui/images/png/chart_linebar.png +0 -0
- yui/images/png/chart_pie.png +0 -0
- yui/images/png/chat.png +0 -0
- yui/images/png/check.png +0 -0
- yui/images/png/check_sheet.png +0 -0
- yui/images/png/circle_cube.png +0 -0
- yui/images/png/circle_cube2.png +0 -0
- yui/images/png/clip_board.png +0 -0
- yui/images/png/close.png +0 -0
- yui/images/png/close_x.png +0 -0
- yui/images/png/continue.png +0 -0
- yui/images/png/contract.png +0 -0
- yui/images/png/contract_2.png +0 -0
- yui/images/png/cube4.png +0 -0
- yui/images/png/custom.png +0 -0
- yui/images/png/custom_care.png +0 -0
- yui/images/png/custom_money.png +0 -0
- yui/images/png/db.png +0 -0
- yui/images/png/dcube.png +0 -0
- yui/images/png/diamond.png +0 -0
- yui/images/png/doc.png +0 -0
- yui/images/png/doc2.png +0 -0
- yui/images/png/doc_percent.png +0 -0
- yui/images/png/doc_rpt.png +0 -0
- yui/images/png/download.png +0 -0
- yui/images/png/download_2.png +0 -0
- yui/images/png/drop.png +0 -0
- yui/images/png/earth.png +0 -0
- yui/images/png/exec_all.png +0 -0
- yui/images/png/execute.png +0 -0
- yui/images/png/export.png +0 -0
- yui/images/png/eye.png +0 -0
- yui/images/png/fangsheng.png +0 -0
- yui/images/png/fapicon.png +0 -0
- yui/images/png/filter.png +0 -0
- yui/images/png/fit_width.png +0 -0
- yui/images/png/fly_up.png +0 -0
- yui/images/png/forward.png +0 -0
- yui/images/png/func.png +0 -0
- yui/images/png/func_group.png +0 -0
- yui/images/png/func_item.png +0 -0
- yui/images/png/function.png +0 -0
- yui/images/png/gauge.png +0 -0
- yui/images/png/goal.png +0 -0
- yui/images/png/golden_star.png +0 -0
- yui/images/png/green_star.png +0 -0
- yui/images/png/grid.png +0 -0
- yui/images/png/grid_1.png +0 -0
- yui/images/png/grid_cube.png +0 -0
- yui/images/png/gridview.png +0 -0
- yui/images/png/hand.png +0 -0
- yui/images/png/heart.png +0 -0
- yui/images/png/hexstar.png +0 -0
- yui/images/png/home.png +0 -0
- yui/images/png/html.png +0 -0
- yui/images/png/index.png +0 -0
- yui/images/png/inout.png +0 -0
- yui/images/png/join.png +0 -0
- yui/images/png/key.png +0 -0
- yui/images/png/label.png +0 -0
- yui/images/png/label_2.png +0 -0
- yui/images/png/last.png +0 -0
- yui/images/png/left.png +0 -0
- yui/images/png/left2.png +0 -0
- yui/images/png/levels.png +0 -0
- yui/images/png/lightning.png +0 -0
- yui/images/png/link.png +0 -0
- yui/images/png/lock.png +0 -0
- yui/images/png/logo.png +0 -0
- yui/images/png/lookup.png +0 -0
- yui/images/png/loop.png +0 -0
- yui/images/png/max.png +0 -0
- yui/images/png/mblocks.png +0 -0
- yui/images/png/milestone.png +0 -0
- yui/images/png/min.png +0 -0
- yui/images/png/minus.png +0 -0
- yui/images/png/money_forward.png +0 -0
- yui/images/png/more.png +0 -0
- yui/images/png/multi_block.png +0 -0
- yui/images/png/next.png +0 -0
- yui/images/png/notebook.png +0 -0
- yui/images/png/nstc.png +0 -0
- yui/images/png/off.png +0 -0
- yui/images/png/okr.png +0 -0
- yui/images/png/open.png +0 -0
- yui/images/png/org.png +0 -0
- yui/images/png/org1.png +0 -0
- yui/images/png/org2.png +0 -0
- yui/images/png/outcome.png +0 -0
- yui/images/png/paper_plane.png +0 -0
- yui/images/png/parts.png +0 -0
- yui/images/png/pause.png +0 -0
- yui/images/png/pc.png +0 -0
- yui/images/png/pc_bar.png +0 -0
- yui/images/png/person_card.png +0 -0
- yui/images/png/person_chart.png +0 -0
- yui/images/png/person_doc.png +0 -0
- yui/images/png/person_fire.png +0 -0
- yui/images/png/person_hire.png +0 -0
- yui/images/png/pie.png +0 -0
- yui/images/png/pie_2.png +0 -0
- yui/images/png/play.png +0 -0
- yui/images/png/plus.png +0 -0
- yui/images/png/red_star.png +0 -0
- yui/images/png/refresh.png +0 -0
- yui/images/png/report.png +0 -0
- yui/images/png/revert.png +0 -0
- yui/images/png/right.png +0 -0
- yui/images/png/right2.png +0 -0
- yui/images/png/right_3.png +0 -0
- yui/images/png/save.png +0 -0
- yui/images/png/save_data.png +0 -0
- yui/images/png/setting.png +0 -0
- yui/images/png/show_normal.png +0 -0
- yui/images/png/site.png +0 -0
- yui/images/png/site_blue.png +0 -0
- yui/images/png/sort.png +0 -0
- yui/images/png/star.png +0 -0
- yui/images/png/stop.png +0 -0
- yui/images/png/sum.png +0 -0
- yui/images/png/sum_1.png +0 -0
- yui/images/png/target.png +0 -0
- yui/images/png/time.png +0 -0
- yui/images/png/to_cloud.png +0 -0
- yui/images/png/todo.png +0 -0
- yui/images/png/tools.png +0 -0
- yui/images/png/tree.png +0 -0
- yui/images/png/trush.png +0 -0
- yui/images/png/tumber.png +0 -0
- yui/images/png/turn_up.png +0 -0
- yui/images/png/two_persons.png +0 -0
- yui/images/png/user.png +0 -0
- yui/images/png/var.png +0 -0
- yui/images/png/view.png +0 -0
- yui/images/png/vv_down.png +0 -0
- yui/images/png/vvv_down.png +0 -0
- yui/images.qrc +189 -0
- yui/images_rc.py +138253 -0
- yui/img.py +185 -0
- yui/qrc_tools.py +54 -0
- yui/wdg.py +1688 -0
- yui/ydict.py +95 -0
- yui/yfield.py +1268 -0
- yui/yform.py +205 -0
- yui/ylookup.py +329 -0
- yui/ymodel.py +516 -0
- yui/ystat.py +1278 -0
- yui/ytable.py +648 -0
- yui/ytree.py +102 -0
- yus/__init__.py +196 -0
- yus/dbm.py +721 -0
- yut/__init__.py +558 -0
- yut/asynx.py +250 -0
- yut/mes.py +206 -0
- yut/rmi.py +196 -0
- yut/win32.py +260 -0
- yut-0.2.20.dist-info/METADATA +297 -0
- yut-0.2.20.dist-info/RECORD +207 -0
- yut-0.2.20.dist-info/WHEEL +4 -0
yui/__init__.py
ADDED
|
@@ -0,0 +1,608 @@
|
|
|
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 import get_attr, is_execute_able, call_exp
|
|
14
|
+
from yut.win32 import set_process_user_model_id
|
|
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='',
|
|
156
|
+
trigger=None,
|
|
157
|
+
icon=None,
|
|
158
|
+
icon_file=None,
|
|
159
|
+
tip_text=None,
|
|
160
|
+
parent=None,
|
|
161
|
+
icon_size: QSize | int = None,
|
|
162
|
+
button_style=Qt.ToolButtonStyle.ToolButtonIconOnly,
|
|
163
|
+
flat=False,
|
|
164
|
+
object_name=None,
|
|
165
|
+
) -> QToolButton:
|
|
166
|
+
btn = QToolButton(parent=parent)
|
|
167
|
+
btn.setToolButtonStyle(button_style)
|
|
168
|
+
btn.setObjectName(object_name)
|
|
169
|
+
if text:
|
|
170
|
+
btn.setText(text)
|
|
171
|
+
if icon:
|
|
172
|
+
btn.setIcon(icon)
|
|
173
|
+
else:
|
|
174
|
+
if icon_file:
|
|
175
|
+
btn.setIcon(load_icon(icon_file))
|
|
176
|
+
if tip_text is not None:
|
|
177
|
+
btn.setToolTip(tip_text)
|
|
178
|
+
else:
|
|
179
|
+
if text:
|
|
180
|
+
btn.setToolTip(text)
|
|
181
|
+
if trigger:
|
|
182
|
+
btn.clicked.connect(trigger)
|
|
183
|
+
if icon_size:
|
|
184
|
+
size = icon_size if isinstance(icon_size, QSize) else QSize(icon_size, icon_size)
|
|
185
|
+
btn.setIconSize(size)
|
|
186
|
+
if flat:
|
|
187
|
+
btn.setStyleSheet("border - style: flat; background: transparent;")
|
|
188
|
+
# btn.setFocusPolicy(Qt.FocusPolicy.NoFocus)
|
|
189
|
+
return btn
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def create_menu_button(menu: QMenu,
|
|
193
|
+
title=None,
|
|
194
|
+
icon_file=None,
|
|
195
|
+
icon=None,
|
|
196
|
+
hovered=False,
|
|
197
|
+
icon_size: QSize | int = None,
|
|
198
|
+
tool_button=False,
|
|
199
|
+
indicator=False,
|
|
200
|
+
object_name=None) -> HoveredButton | HoveredToolButton | QToolButton | QPushButton:
|
|
201
|
+
if icon_size is not None:
|
|
202
|
+
size = icon_size if isinstance(icon_size, QSize) else QSize(icon_size, icon_size)
|
|
203
|
+
else:
|
|
204
|
+
size = QSize(14, 14)
|
|
205
|
+
|
|
206
|
+
if hovered:
|
|
207
|
+
if tool_button:
|
|
208
|
+
btn = HoveredToolButton()
|
|
209
|
+
btn.setSizePolicy(QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed))
|
|
210
|
+
btn.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
|
|
211
|
+
else:
|
|
212
|
+
btn = HoveredButton()
|
|
213
|
+
btn.setFlat(True)
|
|
214
|
+
btn.entered.connect(btn.click)
|
|
215
|
+
else:
|
|
216
|
+
if tool_button:
|
|
217
|
+
btn = QToolButton()
|
|
218
|
+
btn.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
|
|
219
|
+
else:
|
|
220
|
+
btn = QPushButton()
|
|
221
|
+
btn.setFlat(True)
|
|
222
|
+
|
|
223
|
+
btn.setSizePolicy(QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed))
|
|
224
|
+
|
|
225
|
+
if not indicator: # 去掉menu指引箭头
|
|
226
|
+
if isinstance(btn, QToolButton):
|
|
227
|
+
btn.setStyleSheet('QToolButton::menu-indicator {image: none;}')
|
|
228
|
+
if isinstance(btn, QPushButton):
|
|
229
|
+
btn.setStyleSheet('QPushButton::menu-indicator {image: none;}')
|
|
230
|
+
|
|
231
|
+
btn.setMenu(menu)
|
|
232
|
+
btn.setIconSize(size)
|
|
233
|
+
btn.setObjectName(object_name)
|
|
234
|
+
|
|
235
|
+
if title:
|
|
236
|
+
btn.setText(title)
|
|
237
|
+
btn.setToolTip(title)
|
|
238
|
+
|
|
239
|
+
if icon:
|
|
240
|
+
btn.setIcon(icon)
|
|
241
|
+
elif icon_file:
|
|
242
|
+
btn.setIcon(load_icon(icon_file))
|
|
243
|
+
|
|
244
|
+
return btn
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def create_toolbar(buttons=None, actions=None, icon_size=12, parent=None, object_name=None) -> QToolBar:
|
|
248
|
+
tbar = QToolBar(parent=parent)
|
|
249
|
+
tbar.setIconSize(QSize(icon_size, icon_size))
|
|
250
|
+
tbar.setObjectName(object_name)
|
|
251
|
+
if actions:
|
|
252
|
+
tbar.addActions(actions)
|
|
253
|
+
if buttons:
|
|
254
|
+
if actions:
|
|
255
|
+
tbar.addSeparator()
|
|
256
|
+
for btn in buttons:
|
|
257
|
+
tbar.addWidget(btn)
|
|
258
|
+
return tbar
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def pop_info(*args, title=None, sep=' '):
|
|
262
|
+
text = sep.join([str(a) for a in args])
|
|
263
|
+
if not title:
|
|
264
|
+
title = '提示信息'
|
|
265
|
+
QMessageBox.information(get_mainwindow(), title, text)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def pop_question(*args, title=None, sep=' '):
|
|
269
|
+
text = sep.join([str(a) for a in args])
|
|
270
|
+
if not title:
|
|
271
|
+
title = '请确认信息'
|
|
272
|
+
return QMessageBox.question(get_mainwindow(), title, text,
|
|
273
|
+
QMessageBox.StandardButton.Ok,
|
|
274
|
+
QMessageBox.StandardButton.Cancel) == QMessageBox.StandardButton.Ok
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def pop_warning(*args, title=None, sep=' '):
|
|
278
|
+
text = sep.join([str(a) for a in args])
|
|
279
|
+
if not title:
|
|
280
|
+
title = '提示信息'
|
|
281
|
+
QMessageBox.warning(get_mainwindow(), title, text)
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def load_style_sheet(fname):
|
|
285
|
+
style = ''
|
|
286
|
+
for line in open(fname, encoding='utf-8').readlines():
|
|
287
|
+
style += line
|
|
288
|
+
get_app().setStyleSheet(style)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def contrast_color(color):
|
|
292
|
+
luminance = (0.299 * color.red() + 0.587 * color.green() + 0.114 * color.blue()) / 255
|
|
293
|
+
# luminance = (color.red() + color.green() + color.blue()) / (3 * 255)
|
|
294
|
+
if luminance > 0.5:
|
|
295
|
+
contrast = QColor('#000000')
|
|
296
|
+
else:
|
|
297
|
+
contrast = QColor('#FFFFFF')
|
|
298
|
+
return contrast
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def change_font(w, bold=None, size=None, italic=None, underline=None, strike=None):
|
|
302
|
+
font = w.font()
|
|
303
|
+
if bold is not None:
|
|
304
|
+
font.setBold(bold)
|
|
305
|
+
if underline is not None:
|
|
306
|
+
font.setUnderline(underline)
|
|
307
|
+
if italic is not None:
|
|
308
|
+
font.setItalic(italic)
|
|
309
|
+
if strike is not None:
|
|
310
|
+
font.setStrike(strike)
|
|
311
|
+
if size:
|
|
312
|
+
font.setPointSize(size)
|
|
313
|
+
w.setFont(font)
|
|
314
|
+
return w
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def change_item_display(item, bold=None, italic=None, underline=None, strike=None, size=None, color=None,
|
|
318
|
+
background=None):
|
|
319
|
+
font = item.font()
|
|
320
|
+
if bold is not None:
|
|
321
|
+
font.setBold(bold)
|
|
322
|
+
if size:
|
|
323
|
+
font.setPointSize(size)
|
|
324
|
+
if underline is not None:
|
|
325
|
+
font.setUnderline(underline)
|
|
326
|
+
if italic is not None:
|
|
327
|
+
font.setItalic(italic)
|
|
328
|
+
if strike is not None:
|
|
329
|
+
font.setStrike(strike)
|
|
330
|
+
item.setFont(font)
|
|
331
|
+
|
|
332
|
+
if color:
|
|
333
|
+
item.setForeground(color)
|
|
334
|
+
if background:
|
|
335
|
+
item.setBackground(background)
|
|
336
|
+
return item
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
def set_label_color(lb, bk_color=None, fore_color=None):
|
|
340
|
+
pe = QPalette()
|
|
341
|
+
if bk_color:
|
|
342
|
+
lb.setAutoFillBackground(True)
|
|
343
|
+
pe.setColor(QPalette.ColorRole.Window, bk_color)
|
|
344
|
+
if fore_color:
|
|
345
|
+
pe.setColor(QPalette.ColorRole.WindowText, fore_color)
|
|
346
|
+
lb.setPalette(pe)
|
|
347
|
+
return lb
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def set_widget_color(wdg, bk_color=None, fore_color=None):
|
|
351
|
+
palette = wdg.palette()
|
|
352
|
+
if bk_color:
|
|
353
|
+
palette.setColor(QPalette.ColorRole.Window, bk_color)
|
|
354
|
+
if fore_color:
|
|
355
|
+
palette.setColor(QPalette.ColorRole.Text, fore_color)
|
|
356
|
+
wdg.setPalette(palette)
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def create_layout(layout_flag='H', parent=None,
|
|
360
|
+
object_name=None) -> QHBoxLayout | QVBoxLayout | QGridLayout | QFormLayout:
|
|
361
|
+
"""
|
|
362
|
+
依据标记创建布局对象
|
|
363
|
+
:param object_name:
|
|
364
|
+
:param parent:
|
|
365
|
+
:param layout_flag:
|
|
366
|
+
'H' - HBox ;
|
|
367
|
+
'V' - VBox ;
|
|
368
|
+
'F' - FormLayout ;
|
|
369
|
+
'G##' - GridLayout 紧跟在G后面的是Grid布局的列数目,如'G3'表示创建表格布局,每行3列,会将列数加到布局回想的column_num属性中
|
|
370
|
+
:return: QLayout 对象,如果是GridLayout,增加column_num属性,保存打算布置的列数
|
|
371
|
+
"""
|
|
372
|
+
if layout_flag == 'V':
|
|
373
|
+
lyt = QVBoxLayout()
|
|
374
|
+
lyt.setAlignment(Qt.AlignmentFlag.AlignLeft)
|
|
375
|
+
lyt.setSpacing(4)
|
|
376
|
+
elif layout_flag.startswith('G'):
|
|
377
|
+
lyt = QGridLayout()
|
|
378
|
+
if len(layout_flag) > 1:
|
|
379
|
+
lyt.column_num = int(layout_flag[1:])
|
|
380
|
+
lyt.setHorizontalSpacing(4)
|
|
381
|
+
lyt.setVerticalSpacing(4)
|
|
382
|
+
elif layout_flag == 'F':
|
|
383
|
+
lyt = QFormLayout()
|
|
384
|
+
lyt.setAlignment(Qt.AlignmentFlag.AlignTop)
|
|
385
|
+
lyt.setLabelAlignment(
|
|
386
|
+
Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTrailing | Qt.AlignmentFlag.AlignVCenter)
|
|
387
|
+
lyt.setFormAlignment(Qt.AlignmentFlag.AlignLeading | Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
|
|
388
|
+
lyt.setHorizontalSpacing(16)
|
|
389
|
+
lyt.setVerticalSpacing(16)
|
|
390
|
+
else:
|
|
391
|
+
lyt = QHBoxLayout()
|
|
392
|
+
lyt.setAlignment(Qt.AlignmentFlag.AlignVCenter)
|
|
393
|
+
lyt.setSpacing(4)
|
|
394
|
+
lyt.setContentsMargins(0, 0, 0, 0)
|
|
395
|
+
lyt.setParent(parent)
|
|
396
|
+
lyt.setObjectName(object_name)
|
|
397
|
+
return lyt
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
def create_widget(target=QWidget, parent=None, object_name=None) -> QWidget:
|
|
401
|
+
"""
|
|
402
|
+
创建QWidget
|
|
403
|
+
:param object_name:
|
|
404
|
+
:param target: 可以是QWidget实例/QWidget class及其子类/函数/表达式,默认为QWidget class
|
|
405
|
+
:param parent:
|
|
406
|
+
:return:
|
|
407
|
+
"""
|
|
408
|
+
import inspect
|
|
409
|
+
widget = None
|
|
410
|
+
if isinstance(target, QWidget):
|
|
411
|
+
widget = target
|
|
412
|
+
elif inspect.isclass(target):
|
|
413
|
+
widget = target(parent=parent)
|
|
414
|
+
elif is_execute_able(target):
|
|
415
|
+
widget = target()
|
|
416
|
+
elif isinstance(target, str):
|
|
417
|
+
widget = call_exp(target)
|
|
418
|
+
if parent and widget:
|
|
419
|
+
widget.setParent(parent)
|
|
420
|
+
widget.setObjectName(object_name)
|
|
421
|
+
return widget
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def create_layout_widget(target=QWidget, parent=None, layout_flag='H', object_name=None, window_title=None) -> QWidget:
|
|
425
|
+
"""
|
|
426
|
+
创建带布局的widget,并将布局设置为widget的主布局
|
|
427
|
+
:param target: Widget类,默认使用QWidget
|
|
428
|
+
:param layout_flag:
|
|
429
|
+
'H' - HBox ;
|
|
430
|
+
'V' - VBox ;
|
|
431
|
+
'F' - FormLayout ;
|
|
432
|
+
'G##' - GridLayout 紧跟在G后面的是Grid布局的列数目,如'G3'表示创建表格布局,每行3列,会将列数加到布局回想的column_num属性中
|
|
433
|
+
:param parent: 创建widget时使用的父对象
|
|
434
|
+
:param object_name: 对象名,setObjectName
|
|
435
|
+
:param window_title: 窗口标题,setWindowTitle
|
|
436
|
+
:return: QWidget
|
|
437
|
+
"""
|
|
438
|
+
widget = create_widget(target, parent=parent)
|
|
439
|
+
widget.setLayout(create_layout(layout_flag))
|
|
440
|
+
widget.setObjectName(object_name)
|
|
441
|
+
if window_title:
|
|
442
|
+
widget.setWindowTitle(window_title)
|
|
443
|
+
return widget
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
def set_layout_spacing(lyt, h_spacing=0, v_spacing=0):
|
|
447
|
+
if isinstance(lyt, QHBoxLayout):
|
|
448
|
+
lyt.setSpacing(h_spacing)
|
|
449
|
+
elif isinstance(lyt, QVBoxLayout):
|
|
450
|
+
lyt.setSpacing(v_spacing)
|
|
451
|
+
elif isinstance(lyt, QGridLayout):
|
|
452
|
+
lyt.setHorizontalSpacing(h_spacing)
|
|
453
|
+
lyt.setVerticalSpacing(v_spacing)
|
|
454
|
+
elif isinstance(lyt, QFormLayout):
|
|
455
|
+
lyt.setHorizontalSpacing(h_spacing)
|
|
456
|
+
lyt.setVerticalSpacing(v_spacing)
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
def clear_layout(layout: QLayout):
|
|
460
|
+
for i in range(layout.count() - 1, -1, -1):
|
|
461
|
+
item = layout.itemAt(i)
|
|
462
|
+
if item.widget():
|
|
463
|
+
item.widget().deleteLater()
|
|
464
|
+
layout.removeItem(item)
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
def show_in_center(widget):
|
|
468
|
+
screen_rect = get_app().primaryScreen().geometry()
|
|
469
|
+
widget.setGeometry(screen_rect.width() // 2 - widget.width() // 2,
|
|
470
|
+
screen_rect.height() // 2 - widget.height() // 2,
|
|
471
|
+
widget.width(),
|
|
472
|
+
widget.height())
|
|
473
|
+
widget.show()
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
def create_date_edit(date, parent=None, object_name=None) -> QDateEdit:
|
|
477
|
+
edt = QDateTimeEdit(date, parent=parent)
|
|
478
|
+
edt.setObjectName(object_name)
|
|
479
|
+
edt.setCalendarPopup(True)
|
|
480
|
+
edt.setDisplayFormat('yyyy-MM-dd')
|
|
481
|
+
edt.setMinimumWidth(100)
|
|
482
|
+
w = QCalendarWidget(edt)
|
|
483
|
+
w.setGridVisible(True)
|
|
484
|
+
w.setAutoFillBackground(True)
|
|
485
|
+
w.setObjectName('dateEditCalendar')
|
|
486
|
+
w.setMinimumWidth(200)
|
|
487
|
+
w.setMaximumHeight(300)
|
|
488
|
+
edt._cal_widget = w
|
|
489
|
+
edt.setCalendarWidget(edt._cal_widget)
|
|
490
|
+
return edt
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
def filename_for_save(path='.', caption=None, file_filter='*.*'):
|
|
494
|
+
caption = caption if not caption else '请选择待保存的文件位置'
|
|
495
|
+
dlg = QFileDialog(parent=None, caption=caption)
|
|
496
|
+
files = dlg.getSaveFileName(parent=None, caption=caption, dir=path, filter=file_filter)
|
|
497
|
+
if files[0]:
|
|
498
|
+
return files[0]
|
|
499
|
+
else:
|
|
500
|
+
return None
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
def add_to_layout(layout: QLayout, widget: QWidget | QLayout, index=-1):
|
|
504
|
+
if index < 0:
|
|
505
|
+
attr = 'addWidget' if isinstance(widget, QWidget) else 'addLayout'
|
|
506
|
+
else:
|
|
507
|
+
attr = 'insertWidget' if isinstance(widget, QWidget) else 'insertLayout'
|
|
508
|
+
fn_add = get_attr(layout, attr)
|
|
509
|
+
if isinstance(layout, QGridLayout): # Grid布局
|
|
510
|
+
n_count = layout.count()
|
|
511
|
+
if hasattr(layout, 'column_num'):
|
|
512
|
+
column_num = get_attr(layout, 'column_num', 2)
|
|
513
|
+
fn_add(widget, n_count / column_num, n_count % column_num)
|
|
514
|
+
else: # HBox | VBox |GroupBox
|
|
515
|
+
if index < 0:
|
|
516
|
+
fn_add(widget)
|
|
517
|
+
else:
|
|
518
|
+
fn_add(index, widget)
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
def add_field(layout: QLayout, field: QWidget, label=None, index=-1):
|
|
522
|
+
"""
|
|
523
|
+
在布局中添加部件。如果是FormLayout,要求label为QWidget使用addRow
|
|
524
|
+
:param index: -1 - add; >=0 - insert
|
|
525
|
+
:param layout:
|
|
526
|
+
:param field:
|
|
527
|
+
:param label:
|
|
528
|
+
:return:
|
|
529
|
+
"""
|
|
530
|
+
if isinstance(layout, QFormLayout): # Form布局
|
|
531
|
+
layout.addRow(label, field)
|
|
532
|
+
else:
|
|
533
|
+
w = field
|
|
534
|
+
if label is not None: # 创建组合框,否则直接在layout中增加
|
|
535
|
+
g_box = QGroupBox(field.parent())
|
|
536
|
+
g_box.setLayout(QVBoxLayout())
|
|
537
|
+
g_box.layout().setContentsMargins(0, 0, 0, 0)
|
|
538
|
+
g_box.layout().addWidget(field)
|
|
539
|
+
g_box.setTitle(label)
|
|
540
|
+
w = g_box
|
|
541
|
+
add_to_layout(layout, w, index)
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
class WorkMode(Enum):
|
|
545
|
+
"""
|
|
546
|
+
单元的工作模式,显示/编辑
|
|
547
|
+
"""
|
|
548
|
+
DISPLAY = 0 # 显示模式
|
|
549
|
+
EDIT = 1 # 编辑模式
|
|
550
|
+
WATCH = 2 # 监视模式 - 只读显示,但该字段在其它地方改变之后需要更新
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
class EditMode(Enum):
|
|
554
|
+
"""
|
|
555
|
+
表单/列表的编辑模式,新增/修改
|
|
556
|
+
"""
|
|
557
|
+
NEW = 0 # 新增
|
|
558
|
+
MODIFY = 1 # 修改
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
class Stage(Enum):
|
|
562
|
+
"""
|
|
563
|
+
单元的使用场景
|
|
564
|
+
"""
|
|
565
|
+
IN_FORM = 0 # 表单式
|
|
566
|
+
IN_TABLE = 1 # 列表式
|
|
567
|
+
IN_QUERY = 2 # 查询条件
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
class TranslateDirection(Enum):
|
|
571
|
+
TO_TEXT = 0 # 值 -> 显示文字
|
|
572
|
+
TO_VALUE = 1 # 显示文字 -> 值
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
class LookupViewType(Enum):
|
|
576
|
+
"""
|
|
577
|
+
LookupView类型
|
|
578
|
+
"""
|
|
579
|
+
List = 0 # 列表: 无表头,无查询条件,可以筛选
|
|
580
|
+
Table = 1 # 表格: 有表头,可以多列,可以带查询条件以及点击排序
|
|
581
|
+
Tree = 2 # 树:有表头,可以多列,树形展开,无查询条件录入框
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
def alignment_flag(tag):
|
|
585
|
+
"""
|
|
586
|
+
:param tag:
|
|
587
|
+
'>' - 右对齐
|
|
588
|
+
'|' - 水平居中
|
|
589
|
+
'<' - 左对齐
|
|
590
|
+
'^' - 顶对齐
|
|
591
|
+
'-' - 垂直居中
|
|
592
|
+
'_' - 底对齐
|
|
593
|
+
:return:
|
|
594
|
+
"""
|
|
595
|
+
horizontal_alignment, vertical_alignment = Qt.AlignmentFlag.AlignCenter, Qt.AlignmentFlag.AlignVCenter
|
|
596
|
+
for ch, h_flag in {'>': Qt.AlignmentFlag.AlignRight,
|
|
597
|
+
'<': Qt.AlignmentFlag.AlignLeft,
|
|
598
|
+
'|': Qt.AlignmentFlag.AlignCenter
|
|
599
|
+
}.items():
|
|
600
|
+
if ch in tag:
|
|
601
|
+
horizontal_alignment = h_flag
|
|
602
|
+
for ch, v_flag in {'^': Qt.AlignmentFlag.AlignTop,
|
|
603
|
+
'_': Qt.AlignmentFlag.AlignBottom,
|
|
604
|
+
'-': Qt.AlignmentFlag.AlignVCenter
|
|
605
|
+
}.items():
|
|
606
|
+
if ch in tag:
|
|
607
|
+
vertical_alignment = v_flag
|
|
608
|
+
return horizontal_alignment | vertical_alignment
|
|
Binary file
|
yui/images/ico/calc.ico
ADDED
|
Binary file
|
|
Binary file
|
yui/images/ico/dcube.ico
ADDED
|
Binary file
|
yui/images/ico/fap.ico
ADDED
|
Binary file
|
yui/images/ico/ndas.ico
ADDED
|
Binary file
|
yui/images/ico/ndw.ico
ADDED
|
Binary file
|
yui/images/png/3_.png
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
yui/images/png/3i.png
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
yui/images/png/back.png
ADDED
|
Binary file
|
yui/images/png/ball.png
ADDED
|
Binary file
|
yui/images/png/ball2.png
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
yui/images/png/biz_1.png
ADDED
|
Binary file
|
yui/images/png/biz_2.png
ADDED
|
Binary file
|
|
Binary file
|
yui/images/png/bulb.png
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|