ok-script 0.0.49__tar.gz → 0.0.52__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.
Files changed (173) hide show
  1. {ok-script-0.0.49 → ok-script-0.0.52}/PKG-INFO +2 -1
  2. {ok-script-0.0.49 → ok-script-0.0.52}/ok/capture/BaseCaptureMethod.py +14 -4
  3. {ok-script-0.0.49 → ok-script-0.0.52}/ok/capture/adb/DeviceManager.py +3 -4
  4. {ok-script-0.0.49 → ok-script-0.0.52}/ok/color/Color.py +3 -2
  5. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/App.py +11 -4
  6. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/Communicate.py +3 -0
  7. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/MainWindow.py +3 -3
  8. ok-script-0.0.52/ok/gui/about/AboutTab.py +157 -0
  9. ok-script-0.0.52/ok/gui/about/HttpTextEdit.py +22 -0
  10. ok-script-0.0.52/ok/gui/about/VersionCard.py +72 -0
  11. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/resources.py +530 -465
  12. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/start/SelectCaptureListView.py +5 -7
  13. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/tasks/LabelAndDropDown.py +3 -0
  14. ok-script-0.0.52/ok/gui/widget/EmptyCard.py +14 -0
  15. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/widget/Tab.py +7 -3
  16. {ok-script-0.0.49 → ok-script-0.0.52}/ok/task/TaskExecutor.py +8 -2
  17. ok-script-0.0.52/ok/update/GithubMultiDownloader.py +176 -0
  18. ok-script-0.0.52/ok/update/Updater.py +364 -0
  19. ok-script-0.0.52/ok/update/gen_md5.py +23 -0
  20. ok-script-0.0.52/ok/util/__init__.py +0 -0
  21. {ok-script-0.0.49 → ok-script-0.0.52}/ok/util/path.py +46 -0
  22. {ok-script-0.0.49 → ok-script-0.0.52}/ok_script.egg-info/PKG-INFO +2 -1
  23. {ok-script-0.0.49 → ok-script-0.0.52}/ok_script.egg-info/SOURCES.txt +10 -1
  24. {ok-script-0.0.49 → ok-script-0.0.52}/ok_script.egg-info/requires.txt +1 -0
  25. ok-script-0.0.52/ok_script.egg-info/top_level.txt +2 -0
  26. {ok-script-0.0.49 → ok-script-0.0.52}/setup.py +3 -2
  27. ok-script-0.0.52/tests/__init__.py +3 -0
  28. ok-script-0.0.52/tests/test_updater.py +25 -0
  29. ok-script-0.0.49/ok/gui/about/AboutTab.py +0 -24
  30. ok-script-0.0.49/ok_script.egg-info/top_level.txt +0 -1
  31. {ok-script-0.0.49 → ok-script-0.0.52}/README.md +0 -0
  32. {ok-script-0.0.49 → ok-script-0.0.52}/ok/OK.py +0 -0
  33. {ok-script-0.0.49 → ok-script-0.0.52}/ok/__init__.py +0 -0
  34. {ok-script-0.0.49 → ok-script-0.0.52}/ok/capture/HwndWindow.py +0 -0
  35. {ok-script-0.0.49 → ok-script-0.0.52}/ok/capture/__init__.py +0 -0
  36. {ok-script-0.0.49 → ok-script-0.0.52}/ok/capture/adb/ADBCaptureMethod.py +0 -0
  37. {ok-script-0.0.49 → ok-script-0.0.52}/ok/capture/adb/WindowsCaptureFactory.py +0 -0
  38. {ok-script-0.0.49 → ok-script-0.0.52}/ok/capture/adb/__init__.py +0 -0
  39. {ok-script-0.0.49 → ok-script-0.0.52}/ok/capture/adb/bin/__init__.py +0 -0
  40. {ok-script-0.0.49 → ok-script-0.0.52}/ok/capture/adb/targets.py +0 -0
  41. {ok-script-0.0.49 → ok-script-0.0.52}/ok/capture/adb/vbox.py +0 -0
  42. {ok-script-0.0.49 → ok-script-0.0.52}/ok/capture/windows/BaseWindowsCaptureMethod.py +0 -0
  43. {ok-script-0.0.49 → ok-script-0.0.52}/ok/capture/windows/BitBltCaptureMethod.py +0 -0
  44. {ok-script-0.0.49 → ok-script-0.0.52}/ok/capture/windows/DesktopDuplicationCaptureMethod.py +0 -0
  45. {ok-script-0.0.49 → ok-script-0.0.52}/ok/capture/windows/WindowsGraphicsCaptureMethod.py +0 -0
  46. {ok-script-0.0.49 → ok-script-0.0.52}/ok/capture/windows/__init__.py +0 -0
  47. {ok-script-0.0.49 → ok-script-0.0.52}/ok/capture/windows/d3d11.py +0 -0
  48. {ok-script-0.0.49 → ok-script-0.0.52}/ok/capture/windows/dump.py +0 -0
  49. {ok-script-0.0.49 → ok-script-0.0.52}/ok/capture/windows/utils.py +0 -0
  50. {ok-script-0.0.49 → ok-script-0.0.52}/ok/capture/windows/window.py +0 -0
  51. {ok-script-0.0.49 → ok-script-0.0.52}/ok/color/__init__.py +0 -0
  52. {ok-script-0.0.49 → ok-script-0.0.52}/ok/config/Config.py +0 -0
  53. {ok-script-0.0.49 → ok-script-0.0.52}/ok/config/InfoDict.py +0 -0
  54. {ok-script-0.0.49 → ok-script-0.0.52}/ok/config/__init__.py +0 -0
  55. {ok-script-0.0.49 → ok-script-0.0.52}/ok/feature/Box.py +0 -0
  56. {ok-script-0.0.49 → ok-script-0.0.52}/ok/feature/Feature.py +0 -0
  57. {ok-script-0.0.49 → ok-script-0.0.52}/ok/feature/FeatureSet.py +0 -0
  58. {ok-script-0.0.49 → ok-script-0.0.52}/ok/feature/FindFeature.py +0 -0
  59. {ok-script-0.0.49 → ok-script-0.0.52}/ok/feature/__init__.py +0 -0
  60. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/MessageWindow.py +0 -0
  61. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/TabTitles.py +0 -0
  62. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/__init__.py +0 -0
  63. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/about/__init__.py +0 -0
  64. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/common/OKIcon.py +0 -0
  65. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/common/__init__.py +0 -0
  66. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/common/config.py +0 -0
  67. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/common/style_sheet.py +0 -0
  68. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/debug/AspectRatioWidget.py +0 -0
  69. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/debug/DebugTab.py +0 -0
  70. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/debug/FrameWidget.py +0 -0
  71. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/debug/InfoWidget.py +0 -0
  72. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/debug/LoggerWidget.py +0 -0
  73. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/debug/Screenshot.py +0 -0
  74. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/debug/__init__.py +0 -0
  75. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/i18n/__init__.py +0 -0
  76. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/i18n/path.py +0 -0
  77. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/i18n/update.py +0 -0
  78. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/icon/__init__.py +0 -0
  79. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/icon/icon.py +0 -0
  80. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/overlay/OverlayWindow.py +0 -0
  81. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/overlay/__init__.py +0 -0
  82. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/qss/__init__.py +0 -0
  83. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/settings/SettingTab.py +0 -0
  84. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/settings/__init__.py +0 -0
  85. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/start/SelectHwndWindow.py +0 -0
  86. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/start/StartCard.py +0 -0
  87. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/start/StartTab.py +0 -0
  88. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/start/__init__.py +0 -0
  89. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/tasks/ConfigItemFactory.py +0 -0
  90. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/tasks/ConfigLabelAndWidget.py +0 -0
  91. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/tasks/LabelAndDoubleSpinBox.py +0 -0
  92. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/tasks/LabelAndLineEdit.py +0 -0
  93. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/tasks/LabelAndList.py +0 -0
  94. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/tasks/LabelAndSpinBox.py +0 -0
  95. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/tasks/LabelAndSwitchButton.py +0 -0
  96. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/tasks/LabelAndWidget.py +0 -0
  97. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/tasks/ModifyListDialog.py +0 -0
  98. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/tasks/ModifyListItem.py +0 -0
  99. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/tasks/OneTimeTaskTab.py +0 -0
  100. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/tasks/StartButton.py +0 -0
  101. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/tasks/TaskCard.py +0 -0
  102. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/tasks/TaskOpButton.py +0 -0
  103. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/tasks/TooltipTableWidget.py +0 -0
  104. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/tasks/TriggerTaskTab.py +0 -0
  105. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/tasks/__init__.py +0 -0
  106. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/util/Alert.py +0 -0
  107. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/util/InitWorker.py +0 -0
  108. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/util/__init__.py +0 -0
  109. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/widget/Card.py +0 -0
  110. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/widget/FramelessDialog.py +0 -0
  111. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/widget/ListTableWidgetItem.py +0 -0
  112. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/widget/NumericTableWidgetItem.py +0 -0
  113. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/widget/StatusBar.py +0 -0
  114. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/widget/TabWidget.py +0 -0
  115. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/widget/UpdateConfigWidgetItem.py +0 -0
  116. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/widget/YesNonWidgetItem.py +0 -0
  117. {ok-script-0.0.49 → ok-script-0.0.52}/ok/gui/widget/__init__.py +0 -0
  118. {ok-script-0.0.49 → ok-script-0.0.52}/ok/interaction/ADBInteraction.py +0 -0
  119. {ok-script-0.0.49 → ok-script-0.0.52}/ok/interaction/BaseInteraction.py +0 -0
  120. {ok-script-0.0.49 → ok-script-0.0.52}/ok/interaction/Win32Interaction.py +0 -0
  121. {ok-script-0.0.49 → ok-script-0.0.52}/ok/interaction/__init__.py +0 -0
  122. {ok-script-0.0.49 → ok-script-0.0.52}/ok/logging/Logger.py +0 -0
  123. {ok-script-0.0.49 → ok-script-0.0.52}/ok/logging/__init__.py +0 -0
  124. {ok-script-0.0.49 → ok-script-0.0.52}/ok/ocr/OCR.py +0 -0
  125. {ok-script-0.0.49 → ok-script-0.0.52}/ok/ocr/__init__.py +0 -0
  126. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/Windows/Foundation/Collections.py +0 -0
  127. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/Windows/Foundation/__init__.py +0 -0
  128. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/Windows/Globalization/__init__.py +0 -0
  129. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/Windows/Graphics/Capture/__init__.py +0 -0
  130. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/Windows/Graphics/DirectX/Direct3D11/__init__.py +0 -0
  131. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/Windows/Graphics/DirectX/__init__.py +0 -0
  132. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/Windows/Graphics/Imaging/__init__.py +0 -0
  133. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/Windows/Graphics/__init__.py +0 -0
  134. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/Windows/Media/Ocr/__init__.py +0 -0
  135. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/Windows/Media/__init__.py +0 -0
  136. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/Windows/Security/Cryptography/__init__.py +0 -0
  137. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/Windows/Security/__init__.py +0 -0
  138. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/Windows/Storage/Streams/__init__.py +0 -0
  139. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/Windows/Storage/__init__.py +0 -0
  140. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/Windows/__init__.py +0 -0
  141. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/__init__.py +0 -0
  142. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/delegate.py +0 -0
  143. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/export.py +0 -0
  144. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/idldsl.py +0 -0
  145. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/inspectable.py +0 -0
  146. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/roapi.py +0 -0
  147. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/types.py +0 -0
  148. {ok-script-0.0.49 → ok-script-0.0.52}/ok/rotypes/winstring.py +0 -0
  149. {ok-script-0.0.49 → ok-script-0.0.52}/ok/save/BlackBarProcessor.py +0 -0
  150. {ok-script-0.0.49 → ok-script-0.0.52}/ok/save/PostProcessor.py +0 -0
  151. {ok-script-0.0.49 → ok-script-0.0.52}/ok/save/SaveByInterval.py +0 -0
  152. {ok-script-0.0.49 → ok-script-0.0.52}/ok/save/SaveByKeyPress.py +0 -0
  153. {ok-script-0.0.49 → ok-script-0.0.52}/ok/save/SaveMethodBase.py +0 -0
  154. {ok-script-0.0.49 → ok-script-0.0.52}/ok/save/__init__.py +0 -0
  155. {ok-script-0.0.49 → ok-script-0.0.52}/ok/scene/FeatureScene.py +0 -0
  156. {ok-script-0.0.49 → ok-script-0.0.52}/ok/scene/Scene.py +0 -0
  157. {ok-script-0.0.49 → ok-script-0.0.52}/ok/scene/__init__.py +0 -0
  158. {ok-script-0.0.49 → ok-script-0.0.52}/ok/stats/StreamStats.py +0 -0
  159. {ok-script-0.0.49 → ok-script-0.0.52}/ok/stats/__init__.py +0 -0
  160. {ok-script-0.0.49 → ok-script-0.0.52}/ok/task/BaseTask.py +0 -0
  161. {ok-script-0.0.49 → ok-script-0.0.52}/ok/task/ExecutorOperation.py +0 -0
  162. {ok-script-0.0.49 → ok-script-0.0.52}/ok/task/OneTimeTask.py +0 -0
  163. {ok-script-0.0.49 → ok-script-0.0.52}/ok/task/TriggerTask.py +0 -0
  164. {ok-script-0.0.49 → ok-script-0.0.52}/ok/task/__init__.py +0 -0
  165. {ok-script-0.0.49/ok/util → ok-script-0.0.52/ok/update}/__init__.py +0 -0
  166. {ok-script-0.0.49 → ok-script-0.0.52}/ok/util/exit_event.py +0 -0
  167. {ok-script-0.0.49 → ok-script-0.0.52}/ok/util/json.py +0 -0
  168. {ok-script-0.0.49 → ok-script-0.0.52}/ok/util/list.py +0 -0
  169. {ok-script-0.0.49 → ok-script-0.0.52}/ok/util/thread.py +0 -0
  170. {ok-script-0.0.49 → ok-script-0.0.52}/ok/util/win32_process.py +0 -0
  171. {ok-script-0.0.49 → ok-script-0.0.52}/ok/util/yaml.py +0 -0
  172. {ok-script-0.0.49 → ok-script-0.0.52}/ok_script.egg-info/dependency_links.txt +0 -0
  173. {ok-script-0.0.49 → ok-script-0.0.52}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ok-script
3
- Version: 0.0.49
3
+ Version: 0.0.52
4
4
  Summary: Automation with Computer Vision for Python
5
5
  Home-page: https://github.com/ok-oldking/ok-script
6
6
  Author: ok-oldking
@@ -21,6 +21,7 @@ Requires-Dist: PySide6-Fluent-Widgets>=1.5.6
21
21
  Requires-Dist: psutil>=5.9.8
22
22
  Requires-Dist: opencv-python>=4.9.0.80
23
23
  Requires-Dist: ok-d3dshot>=0.1.5
24
+ Requires-Dist: py7zr>=0.21.0
24
25
 
25
26
  # ok-script
26
27
 
@@ -1,5 +1,9 @@
1
1
  import numpy as np
2
2
 
3
+ from ok.logging.Logger import get_logger
4
+
5
+ logger = get_logger(__name__)
6
+
3
7
 
4
8
  class CaptureException(Exception):
5
9
  pass
@@ -21,13 +25,19 @@ class BaseCaptureMethod:
21
25
  @property
22
26
  def width(self):
23
27
  if self._size[0] == 0:
24
- self.get_frame()
28
+ try:
29
+ self.get_frame()
30
+ except Exception as e:
31
+ logger.error('get frame error')
25
32
  return self._size[0]
26
33
 
27
34
  @property
28
35
  def height(self):
29
36
  if self._size[1] == 0:
30
- self.get_frame()
37
+ try:
38
+ self.get_frame()
39
+ except Exception as e:
40
+ logger.error('get frame error')
31
41
  return self._size[1]
32
42
 
33
43
  def get_frame(self) -> np.ndarray | None:
@@ -35,8 +45,8 @@ class BaseCaptureMethod:
35
45
  frame = self.do_get_frame()
36
46
  if frame is not None:
37
47
  self._size = (frame.shape[1], frame.shape[0])
38
- if frame.shape[2] == 4:
39
- frame = frame[:, :, :3]
48
+ if frame.shape[2] == 4:
49
+ frame = frame[:, :, :3]
40
50
  return frame
41
51
  except Exception as e:
42
52
  raise CaptureException() from e
@@ -1,12 +1,10 @@
1
1
  import threading
2
2
 
3
3
  import win32gui
4
- from adbutils import AdbError
5
4
 
6
5
  from ok.capture.HwndWindow import HwndWindow, find_hwnd_by_title_and_exe
7
6
  from ok.capture.adb.ADBCaptureMethod import ADBCaptureMethod, do_screencap
8
7
  from ok.capture.adb.WindowsCaptureFactory import update_capture_method
9
- from ok.capture.adb.vbox import installed_emulator
10
8
  from ok.capture.windows.window import get_window_bounds
11
9
  from ok.config.Config import Config
12
10
  from ok.gui.Communicate import communicate
@@ -36,8 +34,7 @@ class DeviceManager:
36
34
  "DeviceManager")
37
35
  self.thread = None
38
36
  self.capture_method = None
39
- self.update_pc_device()
40
- self.start()
37
+ self.refresh()
41
38
 
42
39
  def refresh(self):
43
40
  if self.thread is None or not self.thread.is_alive():
@@ -121,6 +118,7 @@ class DeviceManager:
121
118
  return
122
119
  if not fast:
123
120
  self.connect_all()
121
+ from ok.capture.adb.vbox import installed_emulator
124
122
  installed_emulators = [] if fast else installed_emulator()
125
123
  for device in self.adb.list():
126
124
  logger.debug(f'adb.list() {device}')
@@ -295,6 +293,7 @@ class DeviceManager:
295
293
  def shell(self, *args, **kwargs):
296
294
  device = self.device
297
295
  if device is not None:
296
+ from adbutils import AdbError
298
297
  try:
299
298
  return device.shell(*args, **kwargs)
300
299
  except AdbError as e:
@@ -17,8 +17,9 @@ def calculate_color_percentage(image, color_ranges, box=None):
17
17
  # Check if the ROI is within the image bounds
18
18
  if box is not None:
19
19
  if (box.x >= 0 and box.y >= 0 and
20
- box.x + box.width <= image.shape[1] and # image.shape[1] is the width of the image
21
- box.y + box.height <= image.shape[0]): # image.shape[0] is the height of the image
20
+ box.x + box.width <= image.shape[1] and # image.shape[1] is the width of the image
21
+ box.y + box.height <= image.shape[
22
+ 0]) and box.width > 0 and box.height > 0: # image.shape[0] is the height of the image
22
23
 
23
24
  # Extract the region of interest (ROI) using slicing
24
25
 
@@ -8,11 +8,13 @@ from qfluentwidgets import FluentTranslator, qconfig, Theme
8
8
 
9
9
  import ok
10
10
  import ok.gui.resources
11
+ from ok.gui.Communicate import communicate
11
12
  from ok.gui.MainWindow import MainWindow
12
13
  from ok.gui.MessageWindow import MessageWindow
13
14
  from ok.gui.i18n.path import i18n_path
14
15
  from ok.gui.overlay.OverlayWindow import OverlayWindow
15
16
  from ok.logging.Logger import get_logger
17
+ from ok.update.Updater import Updater
16
18
 
17
19
  logger = get_logger(__name__)
18
20
 
@@ -29,6 +31,7 @@ class App:
29
31
  QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
30
32
 
31
33
  self.app = QApplication(sys.argv)
34
+ communicate.quit.connect(self.app.quit)
32
35
  self.app.setAttribute(Qt.AA_DontCreateNativeWidgetSiblings)
33
36
  qconfig.theme = Theme.AUTO
34
37
 
@@ -55,6 +58,8 @@ class App:
55
58
  else:
56
59
  logger.debug(f"No translation available for {self.locale}, falling back to English/default. {full_path}")
57
60
 
61
+ self.updater = Updater(self.config, exit_event)
62
+
58
63
  def center_window(self, window):
59
64
  screen = self.app.primaryScreen()
60
65
  size = screen.size()
@@ -75,8 +80,9 @@ class App:
75
80
  self.show_message_window(title, content)
76
81
 
77
82
  def show_main_window(self):
78
- self.main_window = MainWindow(self.icon, self.overlay, self.about, exit_event=self.exit_event)
79
- self.main_window.setWindowTitle(f'{self.title} {self.version}') # Set the window title here
83
+ self.main_window = MainWindow(self.icon, self.title, self.version, self.overlay, self.about,
84
+ exit_event=self.exit_event)
85
+ # Set the window title here
80
86
  self.main_window.setWindowIcon(self.icon)
81
87
  if self.overlay and ok.gui.device_manager.hwnd is not None:
82
88
  self.overlay_window = OverlayWindow(ok.gui.device_manager.hwnd)
@@ -104,5 +110,6 @@ class App:
104
110
  def exec(self):
105
111
  sys.exit(self.app.exec())
106
112
 
107
- def quit(self):
108
- self.app.quit()
113
+ @staticmethod
114
+ def quit():
115
+ communicate.quit.emit()
@@ -20,6 +20,9 @@ class Communicate(QObject):
20
20
  config_validation: Signal = Signal(str)
21
21
  tab = Signal(str)
22
22
  capture_error = Signal()
23
+ check_update = Signal(str)
24
+ download_update = Signal(float, str, bool, str)
25
+ quit = Signal()
23
26
 
24
27
  def emit_draw_box(self, key: str = None, boxes=None, color=None, frame=None):
25
28
  self.draw_box.emit(key, boxes, color, frame)
@@ -20,7 +20,7 @@ class Communicate(QObject):
20
20
 
21
21
 
22
22
  class MainWindow(MSFluentWindow):
23
- def __init__(self, icon, debug=False, about=None, exit_event=None):
23
+ def __init__(self, icon, title, version, debug=False, about=None, exit_event=None):
24
24
  super().__init__()
25
25
  self.exit_event = exit_event
26
26
  self.start_tab = StartTab()
@@ -42,11 +42,11 @@ class MainWindow(MSFluentWindow):
42
42
  # self.addSubInterface(debug_tab, FluentIcon.COMMAND_PROMPT, self.tr('Debug'))
43
43
  # ... Add other tabs similarly
44
44
  if about:
45
- about_tab = AboutTab(about)
45
+ about_tab = AboutTab(icon, title, version, about)
46
46
  self.addSubInterface(about_tab, FluentIcon.QUESTION, self.tr('About'),
47
47
  position=NavigationItemPosition.BOTTOM)
48
48
  # Styling the tabs and content if needed, for example:
49
- self.setWindowTitle("Close Event Example")
49
+ self.setWindowTitle(f'{title} {version}')
50
50
 
51
51
  communicate.executor_paused.connect(self.executor_paused)
52
52
  communicate.tab.connect(self.navigate_tab)
@@ -0,0 +1,157 @@
1
+ from PySide6.QtCore import Qt
2
+ from PySide6.QtWidgets import QHBoxLayout, QLabel
3
+ from qfluentwidgets import PushButton, InfoBar, InfoBarPosition, MessageBox
4
+
5
+ import ok.gui
6
+ from ok.capture.windows.dump import dump_threads
7
+ from ok.gui.Communicate import communicate
8
+ from ok.gui.about.VersionCard import VersionCard
9
+ from ok.gui.widget.Tab import Tab
10
+ from ok.logging.Logger import get_logger
11
+
12
+ logger = get_logger(__name__)
13
+
14
+
15
+ class AboutTab(Tab):
16
+ def __init__(self, icon, title, version, about):
17
+ super().__init__()
18
+ self.version_card = VersionCard(icon, title, version, self)
19
+ # Create a QTextEdit instance
20
+ self.addWidget(self.version_card)
21
+ if ok.gui.app.updater.enabled():
22
+ self.download_latest_button = PushButton(self.tr('Download'))
23
+ self.download_latest_button.clicked.connect(self.download_latest)
24
+
25
+ self.latest_hbox = QHBoxLayout()
26
+ self.addLayout(self.latest_hbox)
27
+ self.latest_label = QLabel()
28
+ self.latest_label.setWordWrap(True)
29
+ self.latest_hbox.addWidget(self.latest_label, stretch=1)
30
+ self.latest_hbox.addWidget(self.download_latest_button, stretch=0)
31
+
32
+ self.download_stable_button = PushButton(self.tr('Download'))
33
+ self.download_stable_button.resize(self.download_stable_button.sizeHint())
34
+ self.download_stable_button.clicked.connect(self.download_stable)
35
+ self.stable_hbox = QHBoxLayout()
36
+ self.stable_label = QLabel()
37
+ self.stable_label.setWordWrap(True)
38
+ self.addLayout(self.stable_hbox)
39
+ self.stable_hbox.addWidget(self.stable_label, stretch=1)
40
+ self.stable_hbox.addWidget(self.download_stable_button, stretch=0)
41
+
42
+ communicate.download_update.connect(self.download_update)
43
+
44
+ self.update_update_buttons(0)
45
+ about_label = QLabel()
46
+ about_label.setText(about)
47
+ about_label.setWordWrap(True)
48
+ about_label.setOpenExternalLinks(True)
49
+
50
+ # Set the layout on the widget
51
+ self.addWidget(about_label)
52
+ if ok.gui.ok.debug:
53
+ dump_button = PushButton(self.tr("Dump Threads(HotKey:Ctrl+Alt+D)"))
54
+ dump_button.clicked.connect(dump_threads)
55
+ self.addWidget(dump_button)
56
+
57
+ def update_update_buttons(self, percent, progress=""):
58
+ if ok.gui.app.updater.latest_release:
59
+ self.latest_label.setText(self.get_version_text(ok.gui.app.updater.latest_release))
60
+ self.download_latest_button.show()
61
+ self.latest_label.show()
62
+ else:
63
+ self.latest_label.hide()
64
+ self.download_latest_button.hide()
65
+ if ok.gui.app.updater.stable_release:
66
+ self.stable_label.setText(self.get_version_text(ok.gui.app.updater.stable_release))
67
+ self.stable_label.show()
68
+ self.download_stable_button.show()
69
+ else:
70
+ self.stable_label.hide()
71
+ self.download_stable_button.hide()
72
+
73
+ if ok.gui.app.updater.downloading:
74
+ self.download_latest_button.setDisabled(True)
75
+ self.download_stable_button.setDisabled(True)
76
+ else:
77
+ self.download_latest_button.setDisabled(False)
78
+ self.download_stable_button.setDisabled(False)
79
+
80
+ if ok.gui.app.updater.to_update:
81
+ if ok.gui.app.updater.to_update.get('release') == ok.gui.app.updater.latest_release:
82
+ self.download_latest_button.setText(self.tr('Update'))
83
+ else:
84
+ self.download_stable_button.setText(self.tr('Update'))
85
+ else:
86
+ self.download_latest_button.setText(self.tr('Download'))
87
+ self.download_stable_button.setText(self.tr('Download'))
88
+
89
+ def get_version_text(self, release):
90
+ text = "<h3>{title}: {version} ({size})</h3>"
91
+ if release.get('prerelease'):
92
+ title = self.tr('Beta Version')
93
+ else:
94
+ title = self.tr('Release Version')
95
+ text = text.format(title=title, version=release.get('version'), size=release.get('readable_size'))
96
+ text += "<p>{date}</p>".format(date=release.get('date'))
97
+ text += "<p>{notes}</p>".format(notes=text_to_html_paragraphs(release.get('notes')))
98
+ return text
99
+
100
+ def do_update(self):
101
+ ok.gui.app.updater.async_run(lambda: ok.gui.app.updater.update())
102
+
103
+ def download_update(self, percent, progress, done, error):
104
+ message = ""
105
+ if done:
106
+ if error:
107
+ title = self.tr('Download Error:')
108
+ message = error
109
+ InfoBar.error(
110
+ title=title,
111
+ content=message,
112
+ orient=Qt.Horizontal,
113
+ isClosable=True,
114
+ position=InfoBarPosition.TOP,
115
+ duration=5000, # won't disappear automatically
116
+ parent=self
117
+ )
118
+ else:
119
+ self.show_update_dialog()
120
+
121
+ self.update_update_buttons(percent, progress)
122
+
123
+ def show_update_dialog(self):
124
+ title = self.tr('Update Now')
125
+ content = self.tr(
126
+ "Are you sure you want to update to {version}?".format(
127
+ version=ok.gui.app.updater.to_update.get(
128
+ 'version'))) + '\n\n' + ok.gui.app.updater.to_update.get(
129
+ 'notes')
130
+
131
+ w = MessageBox(title, content, self.window())
132
+ w.setContentCopyable(True)
133
+ if w.exec():
134
+ logger.info("user click update")
135
+ self.do_update()
136
+
137
+ def download_latest(self):
138
+ if ok.gui.app.updater.to_update and ok.gui.app.updater.to_update.get(
139
+ 'release') == ok.gui.app.updater.latest_release:
140
+ self.show_update_dialog()
141
+ else:
142
+ ok.gui.app.updater.async_run(lambda: ok.gui.app.updater.download(ok.gui.app.updater.latest_release))
143
+
144
+ def download_stable(self):
145
+ if ok.gui.app.updater.to_update and ok.gui.app.updater.to_update.get(
146
+ 'release') == ok.gui.app.updater.stable_release:
147
+ self.show_update_dialog()
148
+ else:
149
+ ok.gui.app.updater.async_run(lambda: ok.gui.app.updater.download(ok.gui.app.updater.stable_release))
150
+
151
+
152
+ def text_to_html_paragraphs(text):
153
+ # Split the text into lines
154
+ lines = text.split('\n')
155
+
156
+ # Wrap each line in a <p> tag and join them
157
+ return ''.join(f'<p>{line}</p>' for line in lines)
@@ -0,0 +1,22 @@
1
+ from PySide6.QtCore import Qt
2
+ from PySide6.QtWidgets import QApplication
3
+ from qfluentwidgets import TextEdit
4
+
5
+
6
+ class VersionCard(TextEdit):
7
+ """ Sample card """
8
+
9
+ def __init__(self, parent=None):
10
+ super().__init__(parent)
11
+ self.anchor = None
12
+
13
+ def mousePressEvent(self, e):
14
+ self.anchor = self.anchorAt(e.pos())
15
+ if self.anchor:
16
+ QApplication.setOverrideCursor(Qt.PointingHandCursor)
17
+
18
+ def mouseReleaseEvent(self, e):
19
+ if self.anchor:
20
+ QDesktopServices.openUrl(QUrl(self.anchor))
21
+ QApplication.setOverrideCursor(Qt.ArrowCursor)
22
+ self.anchor = None
@@ -0,0 +1,72 @@
1
+ from PySide6.QtCore import Qt
2
+ from PySide6.QtWidgets import QLabel
3
+ from qfluentwidgets import SettingCard, PushButton, ProgressBar, InfoBar, InfoBarPosition
4
+
5
+ import ok
6
+ from ok.gui.Communicate import communicate
7
+
8
+
9
+ class VersionCard(SettingCard):
10
+ """ Sample card """
11
+
12
+ def __init__(self, icon, title, version, parent=None):
13
+ super().__init__(icon, title, version)
14
+ self.downloading_text = QLabel()
15
+ self.hBoxLayout.addWidget(self.downloading_text)
16
+ self.hBoxLayout.addSpacing(16)
17
+
18
+ self.download_bar = ProgressBar(self)
19
+ self.download_bar.setFixedWidth(80)
20
+ self.download_bar.setFixedHeight(6)
21
+ self.hBoxLayout.addWidget(self.download_bar)
22
+ self.hBoxLayout.addSpacing(16)
23
+
24
+ self.check_update_button = PushButton(self.tr("Check for updates"))
25
+ self.check_update_button.clicked.connect(self.check_update)
26
+ self.hBoxLayout.addWidget(self.check_update_button)
27
+ self.hBoxLayout.addSpacing(16)
28
+ self.update_buttons(0, "")
29
+ communicate.check_update.connect(self.update_update)
30
+ communicate.download_update.connect(self.download_update)
31
+
32
+ def download_update(self, percent, progress, done, error):
33
+ self.update_buttons(percent, progress)
34
+
35
+ def update_buttons(self, percent, progress):
36
+ if ok.gui.app.updater.downloading:
37
+ self.downloading_text.show()
38
+ self.downloading_text.setText(
39
+ self.tr('Downloading {progress} {percent}%').format(progress=progress, percent=format(percent, '.1f')))
40
+ self.download_bar.show()
41
+ self.download_bar.setValue(percent)
42
+ else:
43
+ self.downloading_text.hide()
44
+ self.download_bar.hide()
45
+
46
+ def update_update(self, error):
47
+ title = self.tr('Info')
48
+ if ok.gui.app.updater.latest_release or ok.gui.app.updater.stable_release:
49
+ bar = InfoBar.info
50
+ message = self.tr('Found new version!')
51
+ elif error:
52
+ bar = InfoBar.error
53
+ title = self.tr('Check for update error!')
54
+ message = error
55
+ else:
56
+ bar = InfoBar.info
57
+ message = self.tr("This is the newest version!")
58
+ bar(
59
+ title=title,
60
+ content=message,
61
+ orient=Qt.Horizontal,
62
+ isClosable=True,
63
+ position=InfoBarPosition.TOP,
64
+ duration=5000, # won't disappear automatically
65
+ parent=self
66
+ )
67
+ self.check_update_button.setEnabled(True)
68
+
69
+ def check_update(self):
70
+ ok.gui.app.updater.async_run(lambda: ok.gui.app.updater.check_for_updates())
71
+ self.check_update_button.setText(self.tr("Checking for updates"))
72
+ self.check_update_button.setEnabled(False)