RinUI 0.1.4.1__py3-none-any.whl → 0.1.5.2__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.
RinUI/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  from .core import *
2
2
 
3
- __version__ = "0.1.4.1"
3
+ __version__ = "0.1.5.2"
4
4
  __author__ = "RinLit"
@@ -107,7 +107,7 @@ SpinBox {
107
107
  // 恢复滚轮调整数值
108
108
  WheelHandler {
109
109
  id: wheelHandler
110
- target: spin
110
+ target: root
111
111
  onWheel: (event) => {
112
112
  if (!root.focus) {
113
113
  return; // 如果没有焦点,则不处理滚轮事件
RinUI/core/launcher.py CHANGED
@@ -1,9 +1,9 @@
1
- import os
2
1
  import sys
3
2
  from typing import Union
4
3
 
5
4
  from PySide6.QtCore import QCoreApplication, QUrl, QObject
6
5
  from PySide6.QtGui import QIcon
6
+ from PySide6.QtQuick import QQuickWindow
7
7
  from PySide6.QtWidgets import QApplication
8
8
  from PySide6.QtQml import QQmlApplicationEngine
9
9
  from pathlib import Path
@@ -20,6 +20,7 @@ class RinUIWindow:
20
20
  :param qml_path: str or Path, QML file path (eg = "path/to/main.qml")
21
21
  """
22
22
  super().__init__()
23
+ self.windows = None
23
24
  if hasattr(self, "_initialized") and self._initialized:
24
25
  return
25
26
 
@@ -54,9 +55,9 @@ class RinUIWindow:
54
55
 
55
56
  if qml_path is None:
56
57
  raise ValueError("QML path must be provided to load the window.")
57
- self.qml_path = qml_path
58
+ self.qml_path = Path(qml_path)
58
59
 
59
- if os.path.exists(RINUI_PATH):
60
+ if self.qml_path.exists():
60
61
  self.engine.addImportPath(RINUI_PATH)
61
62
  else:
62
63
  raise FileNotFoundError(f"Cannot find RinUI module: {RINUI_PATH}")
@@ -73,8 +74,10 @@ class RinUIWindow:
73
74
 
74
75
  # 窗口设置
75
76
  self.root_window = self.engine.rootObjects()[0]
77
+ self.windows = [self.root_window] + self.root_window.findChildren(QQuickWindow)
76
78
 
77
- self.theme_manager.set_window(self.root_window)
79
+ for window in self.windows:
80
+ self.theme_manager.set_window(window)
78
81
 
79
82
  # 窗口句柄管理
80
83
  self._window_handle_setup()
@@ -91,7 +94,7 @@ class RinUIWindow:
91
94
 
92
95
  from .window import WinEventFilter, WinEventManager
93
96
 
94
- self.win_event_filter = WinEventFilter(self.root_window)
97
+ self.win_event_filter = WinEventFilter(self.windows)
95
98
  self.win_event_manager = WinEventManager()
96
99
 
97
100
  app_instance = QApplication.instance()
@@ -106,6 +109,7 @@ class RinUIWindow:
106
109
  :return:
107
110
  """
108
111
  app_instance = QApplication.instance()
112
+ path = Path(path).as_posix()
109
113
  if app_instance:
110
114
  app_instance.setWindowIcon(QIcon(path)) # 设置应用程序图标
111
115
  self.root_window.setProperty('icon', QUrl.fromLocalFile(path))
RinUI/core/theme.py CHANGED
@@ -135,8 +135,6 @@ class ThemeManager(QObject):
135
135
  except Exception as e:
136
136
  print(f"Failed to load config because of {e}, using default config")
137
137
 
138
- # self.hwnd = None # 窗口句柄
139
-
140
138
  self.start_listener()
141
139
 
142
140
  def start_listener(self):
RinUI/core/window.py CHANGED
@@ -1,10 +1,12 @@
1
1
  import platform
2
+ from typing import Optional
2
3
 
3
4
  from PySide6.QtCore import QAbstractNativeEventFilter, QByteArray, QObject, Slot
4
5
  import ctypes
5
6
  from ctypes import wintypes
6
7
 
7
8
  import win32con
9
+ from PySide6.QtQuick import QQuickWindow
8
10
  from win32gui import ReleaseCapture, GetWindowPlacement, ShowWindow
9
11
  from win32con import SW_MAXIMIZE, SW_RESTORE
10
12
  from win32api import SendMessage
@@ -111,23 +113,38 @@ class WinEventManager(QObject):
111
113
 
112
114
 
113
115
  class WinEventFilter(QAbstractNativeEventFilter):
114
- def __init__(self, window):
116
+ def __init__(self, windows: list):
115
117
  super().__init__()
116
- self.window = window
117
- self.hwnd = int(window.winId())
118
- self.resize_border = 8 # resize 边框宽度
119
-
120
- self.set_window_styles()
121
-
122
- def set_window_styles(self):
123
- """设置必要的窗口样式以启用原生窗口行为"""
124
- style = user32.GetWindowLongPtrW(self.hwnd, -16) # GWL_STYLE
118
+ self.windows = windows # 接受多个窗口
119
+ self.hwnds = {} # 用于存储每个窗口的 hwnd
120
+ self.resize_border = 8
121
+
122
+ for window in self.windows:
123
+ window.visibleChanged.connect(self._on_visible_changed)
124
+ if window.isVisible():
125
+ self._init_window_handle(window)
126
+
127
+ def _on_visible_changed(self, visible: bool):
128
+ for window in self.windows:
129
+ if visible and self.hwnds.get(window) is None:
130
+ self._init_window_handle(window)
131
+
132
+ def _init_window_handle(self, window: QQuickWindow):
133
+ hwnd = int(window.winId())
134
+ self.hwnds[window] = hwnd
135
+ self.set_window_styles(window)
136
+
137
+ def set_window_styles(self, window: QQuickWindow):
138
+ hwnd = self.hwnds.get(window)
139
+ if hwnd is None:
140
+ return
125
141
 
142
+ style = user32.GetWindowLongPtrW(hwnd, -16) # GWL_STYLE
126
143
  style |= WS_CAPTION | WS_THICKFRAME
127
- user32.SetWindowLongPtrW(self.hwnd, -16, style) # GWL_STYLE
144
+ user32.SetWindowLongPtrW(hwnd, -16, style) # GWL_STYLE
128
145
 
129
146
  # 重绘
130
- user32.SetWindowPos(self.hwnd, 0, 0, 0, 0, 0,
147
+ user32.SetWindowPos(hwnd, 0, 0, 0, 0, 0,
131
148
  0x0002 | 0x0001 | 0x0040) # SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED
132
149
 
133
150
  def nativeEventFilter(self, eventType: QByteArray, message):
@@ -146,69 +163,73 @@ class WinEventFilter(QAbstractNativeEventFilter):
146
163
  wParam = wintypes.WPARAM.from_address(message_addr + 2 * ctypes.sizeof(ctypes.c_void_p)).value
147
164
  lParam = wintypes.LPARAM.from_address(message_addr + 3 * ctypes.sizeof(ctypes.c_void_p)).value
148
165
 
149
- if message_id == WM_NCHITTEST:
150
- x = ctypes.c_short(lParam & 0xFFFF).value
151
- y = ctypes.c_short((lParam >> 16) & 0xFFFF).value
152
-
153
- rect = wintypes.RECT()
154
- user32.GetWindowRect(self.hwnd, ctypes.byref(rect))
155
- left, top, right, bottom = rect.left, rect.top, rect.right, rect.bottom
156
- border = self.resize_border
157
-
158
- if left <= x < left + border:
159
- if top <= y < top + border:
160
- return True, 13 # HTTOPLEFT
161
- elif bottom - border <= y < bottom:
162
- return True, 16 # HTBOTTOMLEFT
163
- else:
164
- return True, 10 # HTLEFT
165
- elif right - border <= x < right:
166
- if top <= y < top + border:
167
- return True, 14 # HTTOPRIGHT
168
- elif bottom - border <= y < bottom:
169
- return True, 17 # HTBOTTOMRIGHT
170
- else:
171
- return True, 11 # HTRIGHT
172
- elif top <= y < top + border:
173
- return True, 12 # HTTOP
174
- elif bottom - border <= y < bottom:
175
- return True, 15 # HTBOTTOM
176
-
177
- # 其他区域不处理
178
- return False, 0
179
-
180
- # 移除标题栏
181
- elif message_id == WM_NCCALCSIZE and wParam:
182
- return True, 0
183
-
184
- # 支持动画
185
- elif message_id == WM_SYSCOMMAND:
186
- return False, 0
187
-
188
- # 处理 WM_GETMINMAXINFO 消息以支持 Snap 功能
189
- elif message_id == WM_GETMINMAXINFO:
190
- # 获取屏幕工作区大小
191
- monitor = user32.MonitorFromWindow(self.hwnd, 2) # MONITOR_DEFAULTTONEAREST
192
-
193
- # 使用自定义的 MONITORINFO 结构
194
- monitor_info = MONITORINFO()
195
- monitor_info.cbSize = ctypes.sizeof(MONITORINFO)
196
- monitor_info.dwFlags = 0
197
- user32.GetMonitorInfoW(monitor, ctypes.byref(monitor_info))
198
-
199
- # 获取 MINMAXINFO 结构
200
- minmax_info = MINMAXINFO.from_address(lParam)
201
-
202
- # 设置最大化位置和大小
203
- minmax_info.ptMaxPosition.x = monitor_info.rcWork.left - monitor_info.rcMonitor.left
204
- minmax_info.ptMaxPosition.y = monitor_info.rcWork.top - monitor_info.rcMonitor.top
205
- minmax_info.ptMaxSize.x = monitor_info.rcWork.right - monitor_info.rcWork.left
206
- minmax_info.ptMaxSize.y = monitor_info.rcWork.bottom - monitor_info.rcWork.top
207
-
208
- # 设置最小跟踪大小
209
- minmax_info.ptMinTrackSize.x = 200 # 最小宽度
210
- minmax_info.ptMinTrackSize.y = 150 # 最小高度
211
-
212
- return True, 0
166
+ # 遍历每个窗口,检查哪个窗口收到了消息
167
+ for window in self.windows:
168
+ hwnd_window = self.hwnds.get(window)
169
+ if hwnd_window == hwnd:
170
+ if message_id == WM_NCHITTEST:
171
+ x = ctypes.c_short(lParam & 0xFFFF).value
172
+ y = ctypes.c_short((lParam >> 16) & 0xFFFF).value
173
+
174
+ rect = wintypes.RECT()
175
+ user32.GetWindowRect(hwnd_window, ctypes.byref(rect))
176
+ left, top, right, bottom = rect.left, rect.top, rect.right, rect.bottom
177
+ border = self.resize_border
178
+
179
+ if left <= x < left + border:
180
+ if top <= y < top + border:
181
+ return True, 13 # HTTOPLEFT
182
+ elif bottom - border <= y < bottom:
183
+ return True, 16 # HTBOTTOMLEFT
184
+ else:
185
+ return True, 10 # HTLEFT
186
+ elif right - border <= x < right:
187
+ if top <= y < top + border:
188
+ return True, 14 # HTTOPRIGHT
189
+ elif bottom - border <= y < bottom:
190
+ return True, 17 # HTBOTTOMRIGHT
191
+ else:
192
+ return True, 11 # HTRIGHT
193
+ elif top <= y < top + border:
194
+ return True, 12 # HTTOP
195
+ elif bottom - border <= y < bottom:
196
+ return True, 15 # HTBOTTOM
197
+
198
+ # 其他区域不处理
199
+ return False, 0
200
+
201
+ # 移除标题栏
202
+ elif message_id == WM_NCCALCSIZE and wParam:
203
+ return True, 0
204
+
205
+ # 支持动画
206
+ elif message_id == WM_SYSCOMMAND:
207
+ return False, 0
208
+
209
+ # 处理 WM_GETMINMAXINFO 消息以支持 Snap 功能
210
+ elif message_id == WM_GETMINMAXINFO:
211
+ # 获取屏幕工作区大小
212
+ monitor = user32.MonitorFromWindow(hwnd_window, 2) # MONITOR_DEFAULTTONEAREST
213
+
214
+ # 使用自定义的 MONITORINFO 结构
215
+ monitor_info = MONITORINFO()
216
+ monitor_info.cbSize = ctypes.sizeof(MONITORINFO)
217
+ monitor_info.dwFlags = 0
218
+ user32.GetMonitorInfoW(monitor, ctypes.byref(monitor_info))
219
+
220
+ # 获取 MINMAXINFO 结构
221
+ minmax_info = MINMAXINFO.from_address(lParam)
222
+
223
+ # 设置最大化位置和大小
224
+ minmax_info.ptMaxPosition.x = monitor_info.rcWork.left - monitor_info.rcMonitor.left
225
+ minmax_info.ptMaxPosition.y = monitor_info.rcWork.top - monitor_info.rcMonitor.top
226
+ minmax_info.ptMaxSize.x = monitor_info.rcWork.right - monitor_info.rcWork.left
227
+ minmax_info.ptMaxSize.y = monitor_info.rcWork.bottom - monitor_info.rcWork.top
228
+
229
+ # 设置最小跟踪大小
230
+ minmax_info.ptMinTrackSize.x = 200 # 最小宽度
231
+ minmax_info.ptMinTrackSize.y = 150 # 最小高度
232
+
233
+ return True, 0
213
234
 
214
235
  return False, 0
RinUI/windows/CtrlBtn.qml CHANGED
@@ -26,7 +26,11 @@ Base {
26
26
  } else if (mode===1) {
27
27
  window.showMinimized();
28
28
  } else if (mode===2) {
29
- window.close();
29
+ if (window.transientParent) {
30
+ window.visible = false;
31
+ } else {
32
+ window.close();
33
+ }
30
34
  }
31
35
  }
32
36
 
@@ -18,7 +18,7 @@ ApplicationWindow {
18
18
  color: "transparent"
19
19
 
20
20
  // 自定义属性
21
- property var icon: "../assets/img/default_app_icon.png" // 图标
21
+ property var icon: undefined // 图标
22
22
  property alias titleEnabled: titleBar.titleEnabled
23
23
  property int titleBarHeight: Theme.currentTheme.appearance.dialogTitleBarHeight
24
24
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: RinUI
3
- Version: 0.1.4.1
3
+ Version: 0.1.5.2
4
4
  Summary: A Fluent Design-like UI library for Qt Quick (QML) based on PySide6
5
5
  Author-email: RinLit <lintu233_qwq@icloud.com>
6
6
  Classifier: Programming Language :: Python :: 3
@@ -1,4 +1,4 @@
1
- RinUI/__init__.py,sha256=d9IqpbSfnP6x6uXkS5V5liug1uHaNhct-nbJQXNhEAA,67
1
+ RinUI/__init__.py,sha256=68D7COFIrSHlQKtabW1X-SFZtRz27mLAEQdjxIJWMB0,67
2
2
  RinUI/qmldir,sha256=M0TVfvNm_nrx1s6rxXvUIP-8m3Oc9UhqHDxQfEIdQTA,3959
3
3
  RinUI/assets/fonts/FluentSystemIcons-Index.js,sha256=M2fUmCiOI7A1rxLWMFaekrB4KmasTSwbociYOzHJegE,253422
4
4
  RinUI/assets/fonts/FluentSystemIcons-Resizable.ttf,sha256=-IfF3NT1eODD0vOLVLC0Z2U5bsR6woSQAziX3qD1TqU,1447252
@@ -65,17 +65,17 @@ RinUI/components/StatusAndInfo/ProgressBar.qml,sha256=4q2LKNHNFYChl81Hwhwm_9GcYc
65
65
  RinUI/components/StatusAndInfo/ProgressRing.qml,sha256=aeWl1v3hom-iI2MNkO_FfFkJaJy23Lo49oiL6bwclaM,5088
66
66
  RinUI/components/StatusAndInfo/Toast.qml,sha256=XWZPgFBJnqoWoS6H9W3ycC9JTU1CTzehqVIm2KXhD6Y,6815
67
67
  RinUI/components/StatusAndInfo/ToolTip.qml,sha256=f6S9rG_0GsHQl8BB1m4Niik35s7LngelAasLfFkdR7s,2664
68
- RinUI/components/Text/SpinBox.qml,sha256=rY17yJ3a0ckkl6pX00qVIQQYLmoO-GLtcSZh-WKtPZs,4616
68
+ RinUI/components/Text/SpinBox.qml,sha256=lLJ8J5KPAi42ZK1bM5JUnME8njDsdzTSz_W-Tpp2L8A,4616
69
69
  RinUI/components/Text/Text.qml,sha256=SWJBJtAWkq9XldrX6_BWfCXGRcLQLBNofkRO5NG8q2Q,1714
70
70
  RinUI/components/Text/TextArea.qml,sha256=guhwcFBSEyZkTRT2V0ER3S03xW9WOkH_4U2Oor2I9PY,3706
71
71
  RinUI/components/Text/TextField.qml,sha256=BXuJ16AUQaSh-Og7jaYSNEu9r1PcyG7FQ95DaGciJZs,3556
72
72
  RinUI/components/Text/TextInput.qml,sha256=gyTJmrYi5yuc-j5dDRSbu5PCxiuQo2xNBm6jWL9ezYk,1611
73
73
  RinUI/core/__init__.py,sha256=xNbsFDXuObMebyn0Xsxieenh0fsAEjULqBd9qd8suTY,283
74
74
  RinUI/core/config.py,sha256=h5tbQurVtpnfB10OMTWEZstzsF93zDOPDmbP9NRgvJk,3683
75
- RinUI/core/launcher.py,sha256=ZWBGQP0DT2oWZXvqRK9cW7eRmImZe8L1B1-0ONgaGnc,5812
76
- RinUI/core/theme.py,sha256=r47QltFKy_s-B1neVAjYIx_jOxxtsdJEMP-u-YJ8mpA,9832
75
+ RinUI/core/launcher.py,sha256=pUKcpErcDsDqfTIcZHqG8ErQOHGqkqPnwkUKiEtujBQ,6024
76
+ RinUI/core/theme.py,sha256=GfLFtorGVvRmBCR97hpvwKGVwfrN4AD9FFEIDupVszM,9788
77
77
  RinUI/core/translator.py,sha256=5GK7Iy7-2iMicF8hQr79CwU9UWvCwE-8vGd8QkhJ1h8,1037
78
- RinUI/core/window.py,sha256=KIu3qpN_RKcMc-8o6qxYAWecDVNBtjxCjqUN04RaI6I,7161
78
+ RinUI/core/window.py,sha256=vSbcos5B2gioKev6jiVBMtNzn01_ZvieCly6Pw6U5kI,8408
79
79
  RinUI/hooks/__init__.py,sha256=7sQJlly1ZbiZTzZUkCV2hI_gY-DAxWP_0kLyhZQ2Tm8,74
80
80
  RinUI/hooks/hook-RinUI.py,sha256=VvQui-b3YNuxvhqjRJqLPKdtnWQ6Ev8G9DEgzGNUUUI,116
81
81
  RinUI/languages/en_US.qm,sha256=mVm1ELFdGJN4SK0TAH4wRZ0umTxn5WS62_wY-TVpXIU,16
@@ -96,20 +96,20 @@ RinUI/utils/Position.qml,sha256=QuD_cYdU7ku3L1zxFX8e0ZKDvOOW7xbilP2_ebr7WB8,256
96
96
  RinUI/utils/Severity.qml,sha256=fN3YQ_88kNGB-Z57pzcDrz15r-JPMLPJfNUVqKkYbas,155
97
97
  RinUI/utils/Typography.qml,sha256=EJIlEymSWH4lWyRIrdWD9UZaExgGld81YQF1diaKKq8,232
98
98
  RinUI/utils/qmldir,sha256=W2UTrZ5VPdRO64FZ3Pw-_8B2UPj7A_eHsGrLPvWtiZY,189
99
- RinUI/windows/CtrlBtn.qml,sha256=8wQH3PWYmZ_e6A0_CIdmYa7uIrU6O6MZCG_RR4S4fkg,3152
99
+ RinUI/windows/CtrlBtn.qml,sha256=7o67Ci1eKI22tl00s2klnwdmU9mhyzp8UQOTzF_5XtI,3273
100
100
  RinUI/windows/FluentPage.qml,sha256=J7mXTOyMahdWA8U13rSjesJVsvxklZFQyqwVMiJarT8,2748
101
101
  RinUI/windows/FluentWindow.qml,sha256=CUx9H5crOKtPSCnA6_AUst4PcLEbhSjDRrSuWH8novA,969
102
- RinUI/windows/FluentWindowBase.qml,sha256=rUUHO1lIjIIvrHjKHwSIEn8WOG2kY45mJQQT_KrGZDM,4335
102
+ RinUI/windows/FluentWindowBase.qml,sha256=QV0WwRTL997c2Q8TNvsl8fNXLfkZabQvh0O0kT9NxhI,4308
103
103
  RinUI/windows/TitleBar.qml,sha256=QjnSb27Db2e8o2QniuJUMT0QI6awMbavVNex70Wsy2s,3591
104
104
  RinUI/windows/WindowManager.qml,sha256=f-Il6FCPf3_o6edj5BbscK2XxQd3mmUVnZPZuOO88kc,1037
105
105
  RinUI/windows/qmldir,sha256=oxyWR7Q8dWCrwwCwGNyf3l60qe6s4-beiZWWMAEkKcM,252
106
106
  RinUI/windows/window/ApplicationWindow.qml,sha256=qRaM8IY0TJxfq1j1DogTMyrPjyoXkuWVzxtZQLzRtOQ,167
107
107
  RinUI/windows/window/Window.qml,sha256=90YjjRoaul9qK4FxNy73zTaPuUmLvk_RjcPlBEa7DNI,3189
108
- rinui-0.1.4.1.data/data/LICENSE,sha256=vgoqqpny5vKYu34VDBUWYQKzT7Nn-Xy9y8USmcOCyZQ,1063
109
- rinui-0.1.4.1.data/data/README.md,sha256=8ZcR55RYV2slRAQbhoYhqDTPOLXmewkFSvuA_cE6zD0,3044
110
- rinui-0.1.4.1.dist-info/licenses/LICENSE,sha256=vgoqqpny5vKYu34VDBUWYQKzT7Nn-Xy9y8USmcOCyZQ,1063
111
- rinui-0.1.4.1.dist-info/METADATA,sha256=YmwxS5tHeWcDsCsZxZlH2vYgo3vyXCZSw3-9yvbpBx0,3577
112
- rinui-0.1.4.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
113
- rinui-0.1.4.1.dist-info/entry_points.txt,sha256=taxuZYCggoQa2LPubwcurQYRjBRC4cNYOjWaqOYZVxw,54
114
- rinui-0.1.4.1.dist-info/top_level.txt,sha256=vKKjXBXEw5OFRIzTxZWUC5ZOj0CK5e3atbymBB4eJ6w,6
115
- rinui-0.1.4.1.dist-info/RECORD,,
108
+ rinui-0.1.5.2.data/data/LICENSE,sha256=vgoqqpny5vKYu34VDBUWYQKzT7Nn-Xy9y8USmcOCyZQ,1063
109
+ rinui-0.1.5.2.data/data/README.md,sha256=8ZcR55RYV2slRAQbhoYhqDTPOLXmewkFSvuA_cE6zD0,3044
110
+ rinui-0.1.5.2.dist-info/licenses/LICENSE,sha256=vgoqqpny5vKYu34VDBUWYQKzT7Nn-Xy9y8USmcOCyZQ,1063
111
+ rinui-0.1.5.2.dist-info/METADATA,sha256=19MjmBD4L9YAwV7JCrooUGMA_4OCccUYkULYwJk_FjA,3577
112
+ rinui-0.1.5.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
113
+ rinui-0.1.5.2.dist-info/entry_points.txt,sha256=taxuZYCggoQa2LPubwcurQYRjBRC4cNYOjWaqOYZVxw,54
114
+ rinui-0.1.5.2.dist-info/top_level.txt,sha256=vKKjXBXEw5OFRIzTxZWUC5ZOj0CK5e3atbymBB4eJ6w,6
115
+ rinui-0.1.5.2.dist-info/RECORD,,
File without changes