ok-script 0.0.40__tar.gz → 0.0.41__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 (159) hide show
  1. {ok-script-0.0.40 → ok-script-0.0.41}/PKG-INFO +1 -1
  2. {ok-script-0.0.40 → ok-script-0.0.41}/ok/OK.py +3 -2
  3. {ok-script-0.0.40 → ok-script-0.0.41}/ok/capture/HwndWindow.py +1 -2
  4. {ok-script-0.0.40 → ok-script-0.0.41}/ok/capture/windows/WindowsGraphicsCaptureMethod.py +11 -2
  5. {ok-script-0.0.40 → ok-script-0.0.41}/ok/config/Config.py +36 -21
  6. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/Communicate.py +1 -0
  7. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/MainWindow.py +14 -0
  8. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/debug/Screenshot.py +11 -2
  9. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/tasks/ConfigItemFactory.py +8 -8
  10. ok-script-0.0.41/ok/gui/tasks/ConfigLabelAndWidget.py +16 -0
  11. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/tasks/LabelAndDoubleSpinBox.py +3 -4
  12. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/tasks/LabelAndDropDown.py +3 -4
  13. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/tasks/LabelAndLineEdit.py +3 -4
  14. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/tasks/LabelAndSpinBox.py +3 -4
  15. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/tasks/LabelAndSwitchButton.py +3 -4
  16. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/tasks/ModifyListItem.py +12 -6
  17. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/tasks/TaskCard.py +1 -1
  18. {ok-script-0.0.40 → ok-script-0.0.41}/ok/save/SaveMethodBase.py +1 -0
  19. {ok-script-0.0.40 → ok-script-0.0.41}/ok/task/BaseTask.py +11 -1
  20. {ok-script-0.0.40 → ok-script-0.0.41}/ok/task/ExecutorOperation.py +6 -1
  21. {ok-script-0.0.40 → ok-script-0.0.41}/ok/task/TaskExecutor.py +1 -0
  22. {ok-script-0.0.40 → ok-script-0.0.41}/ok/util/exit_event.py +5 -0
  23. {ok-script-0.0.40 → ok-script-0.0.41}/ok_script.egg-info/PKG-INFO +1 -1
  24. {ok-script-0.0.40 → ok-script-0.0.41}/setup.py +1 -1
  25. ok-script-0.0.40/ok/gui/tasks/ConfigLabelAndWidget.py +0 -10
  26. {ok-script-0.0.40 → ok-script-0.0.41}/README.md +0 -0
  27. {ok-script-0.0.40 → ok-script-0.0.41}/ok/__init__.py +0 -0
  28. {ok-script-0.0.40 → ok-script-0.0.41}/ok/capture/BaseCaptureMethod.py +0 -0
  29. {ok-script-0.0.40 → ok-script-0.0.41}/ok/capture/__init__.py +0 -0
  30. {ok-script-0.0.40 → ok-script-0.0.41}/ok/capture/adb/ADBCaptureMethod.py +0 -0
  31. {ok-script-0.0.40 → ok-script-0.0.41}/ok/capture/adb/DeviceManager.py +0 -0
  32. {ok-script-0.0.40 → ok-script-0.0.41}/ok/capture/adb/__init__.py +0 -0
  33. {ok-script-0.0.40 → ok-script-0.0.41}/ok/capture/adb/bin/__init__.py +0 -0
  34. {ok-script-0.0.40 → ok-script-0.0.41}/ok/capture/adb/targets.py +0 -0
  35. {ok-script-0.0.40 → ok-script-0.0.41}/ok/capture/adb/vbox.py +0 -0
  36. {ok-script-0.0.40 → ok-script-0.0.41}/ok/capture/windows/__init__.py +0 -0
  37. {ok-script-0.0.40 → ok-script-0.0.41}/ok/capture/windows/d3d11.py +0 -0
  38. {ok-script-0.0.40 → ok-script-0.0.41}/ok/capture/windows/dump.py +0 -0
  39. {ok-script-0.0.40 → ok-script-0.0.41}/ok/capture/windows/utils.py +0 -0
  40. {ok-script-0.0.40 → ok-script-0.0.41}/ok/capture/windows/window.py +0 -0
  41. {ok-script-0.0.40 → ok-script-0.0.41}/ok/color/Color.py +0 -0
  42. {ok-script-0.0.40 → ok-script-0.0.41}/ok/color/__init__.py +0 -0
  43. {ok-script-0.0.40 → ok-script-0.0.41}/ok/config/InfoDict.py +0 -0
  44. {ok-script-0.0.40 → ok-script-0.0.41}/ok/config/__init__.py +0 -0
  45. {ok-script-0.0.40 → ok-script-0.0.41}/ok/feature/Box.py +0 -0
  46. {ok-script-0.0.40 → ok-script-0.0.41}/ok/feature/Feature.py +0 -0
  47. {ok-script-0.0.40 → ok-script-0.0.41}/ok/feature/FeatureSet.py +0 -0
  48. {ok-script-0.0.40 → ok-script-0.0.41}/ok/feature/FindFeature.py +0 -0
  49. {ok-script-0.0.40 → ok-script-0.0.41}/ok/feature/__init__.py +0 -0
  50. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/App.py +0 -0
  51. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/MessageWindow.py +0 -0
  52. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/TabTitles.py +0 -0
  53. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/__init__.py +0 -0
  54. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/about/AboutTab.py +0 -0
  55. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/about/__init__.py +0 -0
  56. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/common/OKIcon.py +0 -0
  57. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/common/__init__.py +0 -0
  58. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/common/config.py +0 -0
  59. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/common/style_sheet.py +0 -0
  60. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/debug/AspectRatioWidget.py +0 -0
  61. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/debug/DebugTab.py +0 -0
  62. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/debug/FrameWidget.py +0 -0
  63. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/debug/InfoWidget.py +0 -0
  64. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/debug/LoggerWidget.py +0 -0
  65. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/debug/__init__.py +0 -0
  66. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/i18n/__init__.py +0 -0
  67. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/i18n/path.py +0 -0
  68. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/i18n/update.py +0 -0
  69. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/icon/__init__.py +0 -0
  70. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/icon/icon.py +0 -0
  71. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/overlay/OverlayWindow.py +0 -0
  72. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/overlay/__init__.py +0 -0
  73. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/qss/__init__.py +0 -0
  74. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/resources.py +0 -0
  75. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/settings/SettingTab.py +0 -0
  76. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/settings/__init__.py +0 -0
  77. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/start/SelectCaptureListView.py +0 -0
  78. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/start/SelectHwndWindow.py +0 -0
  79. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/start/StartCard.py +0 -0
  80. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/start/StartTab.py +0 -0
  81. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/start/__init__.py +0 -0
  82. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/tasks/LabelAndList.py +0 -0
  83. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/tasks/LabelAndWidget.py +0 -0
  84. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/tasks/ModifyListDialog.py +0 -0
  85. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/tasks/OneTimeTaskTab.py +0 -0
  86. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/tasks/StartButton.py +0 -0
  87. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/tasks/TaskOpButton.py +0 -0
  88. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/tasks/TooltipTableWidget.py +0 -0
  89. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/tasks/TriggerTaskTab.py +0 -0
  90. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/tasks/__init__.py +0 -0
  91. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/util/Alert.py +0 -0
  92. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/util/InitWorker.py +0 -0
  93. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/util/__init__.py +0 -0
  94. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/widget/Card.py +0 -0
  95. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/widget/FramelessDialog.py +0 -0
  96. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/widget/ListTableWidgetItem.py +0 -0
  97. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/widget/NumericTableWidgetItem.py +0 -0
  98. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/widget/StatusBar.py +0 -0
  99. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/widget/Tab.py +0 -0
  100. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/widget/TabWidget.py +0 -0
  101. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/widget/UpdateConfigWidgetItem.py +0 -0
  102. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/widget/YesNonWidgetItem.py +0 -0
  103. {ok-script-0.0.40 → ok-script-0.0.41}/ok/gui/widget/__init__.py +0 -0
  104. {ok-script-0.0.40 → ok-script-0.0.41}/ok/interaction/ADBInteraction.py +0 -0
  105. {ok-script-0.0.40 → ok-script-0.0.41}/ok/interaction/BaseInteraction.py +0 -0
  106. {ok-script-0.0.40 → ok-script-0.0.41}/ok/interaction/Win32Interaction.py +0 -0
  107. {ok-script-0.0.40 → ok-script-0.0.41}/ok/interaction/__init__.py +0 -0
  108. {ok-script-0.0.40 → ok-script-0.0.41}/ok/logging/Logger.py +0 -0
  109. {ok-script-0.0.40 → ok-script-0.0.41}/ok/logging/__init__.py +0 -0
  110. {ok-script-0.0.40 → ok-script-0.0.41}/ok/ocr/OCR.py +0 -0
  111. {ok-script-0.0.40 → ok-script-0.0.41}/ok/ocr/__init__.py +0 -0
  112. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/Windows/Foundation/Collections.py +0 -0
  113. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/Windows/Foundation/__init__.py +0 -0
  114. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/Windows/Globalization/__init__.py +0 -0
  115. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/Windows/Graphics/Capture/__init__.py +0 -0
  116. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/Windows/Graphics/DirectX/Direct3D11/__init__.py +0 -0
  117. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/Windows/Graphics/DirectX/__init__.py +0 -0
  118. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/Windows/Graphics/Imaging/__init__.py +0 -0
  119. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/Windows/Graphics/__init__.py +0 -0
  120. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/Windows/Media/Ocr/__init__.py +0 -0
  121. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/Windows/Media/__init__.py +0 -0
  122. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/Windows/Security/Cryptography/__init__.py +0 -0
  123. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/Windows/Security/__init__.py +0 -0
  124. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/Windows/Storage/Streams/__init__.py +0 -0
  125. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/Windows/Storage/__init__.py +0 -0
  126. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/Windows/__init__.py +0 -0
  127. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/__init__.py +0 -0
  128. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/delegate.py +0 -0
  129. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/export.py +0 -0
  130. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/idldsl.py +0 -0
  131. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/inspectable.py +0 -0
  132. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/roapi.py +0 -0
  133. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/types.py +0 -0
  134. {ok-script-0.0.40 → ok-script-0.0.41}/ok/rotypes/winstring.py +0 -0
  135. {ok-script-0.0.40 → ok-script-0.0.41}/ok/save/BlackBarProcessor.py +0 -0
  136. {ok-script-0.0.40 → ok-script-0.0.41}/ok/save/PostProcessor.py +0 -0
  137. {ok-script-0.0.40 → ok-script-0.0.41}/ok/save/SaveByInterval.py +0 -0
  138. {ok-script-0.0.40 → ok-script-0.0.41}/ok/save/SaveByKeyPress.py +0 -0
  139. {ok-script-0.0.40 → ok-script-0.0.41}/ok/save/__init__.py +0 -0
  140. {ok-script-0.0.40 → ok-script-0.0.41}/ok/scene/FeatureScene.py +0 -0
  141. {ok-script-0.0.40 → ok-script-0.0.41}/ok/scene/Scene.py +0 -0
  142. {ok-script-0.0.40 → ok-script-0.0.41}/ok/scene/__init__.py +0 -0
  143. {ok-script-0.0.40 → ok-script-0.0.41}/ok/stats/StreamStats.py +0 -0
  144. {ok-script-0.0.40 → ok-script-0.0.41}/ok/stats/__init__.py +0 -0
  145. {ok-script-0.0.40 → ok-script-0.0.41}/ok/task/OneTimeTask.py +0 -0
  146. {ok-script-0.0.40 → ok-script-0.0.41}/ok/task/TriggerTask.py +0 -0
  147. {ok-script-0.0.40 → ok-script-0.0.41}/ok/task/__init__.py +0 -0
  148. {ok-script-0.0.40 → ok-script-0.0.41}/ok/util/__init__.py +0 -0
  149. {ok-script-0.0.40 → ok-script-0.0.41}/ok/util/json.py +0 -0
  150. {ok-script-0.0.40 → ok-script-0.0.41}/ok/util/list.py +0 -0
  151. {ok-script-0.0.40 → ok-script-0.0.41}/ok/util/path.py +0 -0
  152. {ok-script-0.0.40 → ok-script-0.0.41}/ok/util/thread.py +0 -0
  153. {ok-script-0.0.40 → ok-script-0.0.41}/ok/util/win32_process.py +0 -0
  154. {ok-script-0.0.40 → ok-script-0.0.41}/ok/util/yaml.py +0 -0
  155. {ok-script-0.0.40 → ok-script-0.0.41}/ok_script.egg-info/SOURCES.txt +0 -0
  156. {ok-script-0.0.40 → ok-script-0.0.41}/ok_script.egg-info/dependency_links.txt +0 -0
  157. {ok-script-0.0.40 → ok-script-0.0.41}/ok_script.egg-info/requires.txt +0 -0
  158. {ok-script-0.0.40 → ok-script-0.0.41}/ok_script.egg-info/top_level.txt +0 -0
  159. {ok-script-0.0.40 → ok-script-0.0.41}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ok-script
3
- Version: 0.0.40
3
+ Version: 0.0.41
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
@@ -34,7 +34,7 @@ class OK:
34
34
  self.config = config
35
35
  self.init_device_manager()
36
36
  from ok.gui.debug.Screenshot import Screenshot
37
- self.screenshot = Screenshot()
37
+ self.screenshot = Screenshot(self.exit_event)
38
38
  if config.get("use_gui"):
39
39
  from ok.gui.App import App
40
40
  self.app = App(config, self.exit_event)
@@ -123,7 +123,8 @@ class OK:
123
123
  def quit(self):
124
124
  logger.debug('quit app')
125
125
  self.exit_event.set()
126
- self.device_manager.stop()
126
+ if self.device_manager is not None:
127
+ self.device_manager.stop()
127
128
  if self.app:
128
129
  self.app.quit()
129
130
 
@@ -11,7 +11,6 @@ from win32 import win32gui
11
11
  from ok.capture.windows.window import is_foreground_window, get_window_bounds
12
12
  from ok.gui.Communicate import communicate
13
13
  from ok.logging.Logger import get_logger
14
- from ok.util.exit_event import ExitEvent
15
14
 
16
15
  logger = get_logger(__name__)
17
16
 
@@ -41,7 +40,7 @@ class HwndWindow:
41
40
  super().__init__()
42
41
  self.app_exit_event = exit_event
43
42
  self.exe_name = exe_name
44
- self.stop_event = ExitEvent()
43
+ self.stop_event = threading.Event()
45
44
  self.update_title_re(title)
46
45
  self.visible = False
47
46
  self.update_frame_size(frame_width, frame_height)
@@ -32,7 +32,7 @@ class WindowsGraphicsCaptureMethod(BaseCaptureMethod):
32
32
  description = "fast, most compatible, capped at 60fps"
33
33
  last_frame = None
34
34
  last_frame_time = 0
35
- hwnd_window: HwndWindow = None
35
+ _hwnd_window: HwndWindow = None
36
36
  frame_pool = None
37
37
  item = None
38
38
  session = None
@@ -42,7 +42,7 @@ class WindowsGraphicsCaptureMethod(BaseCaptureMethod):
42
42
 
43
43
  def __init__(self, hwnd_window: HwndWindow):
44
44
  super().__init__()
45
- self.hwnd_window = hwnd_window
45
+ self._hwnd_window = hwnd_window
46
46
  self.start_or_stop()
47
47
 
48
48
  def frame_arrived_callback(self, x, y):
@@ -108,6 +108,15 @@ class WindowsGraphicsCaptureMethod(BaseCaptureMethod):
108
108
  return self.get_frame()
109
109
  self.last_frame = img
110
110
 
111
+ @property
112
+ def hwnd_window(self):
113
+ return self._hwnd_window
114
+
115
+ @hwnd_window.setter
116
+ def hwnd_window(self, hwnd_window):
117
+ self._hwnd_window = hwnd_window
118
+ self.start_or_stop()
119
+
111
120
  def connected(self):
112
121
  return self.hwnd_window is not None and self.hwnd_window.exists
113
122
 
@@ -1,16 +1,18 @@
1
+ from ok.gui.Communicate import communicate
1
2
  from ok.util.json import read_json_file, write_json_file
2
3
  from ok.util.path import get_path_relative_to_exe
3
4
 
4
5
 
5
6
  class Config:
6
- def __init__(self, default, folder, name):
7
+ def __init__(self, default, folder, name, validator=None):
7
8
  super().__init__()
8
9
  self.default = default
10
+ self.validator = validator
9
11
  self.config_file = get_path_relative_to_exe(folder, f"{name}.json")
10
12
  self.config = read_json_file(self.config_file)
11
13
  if self.config is None:
12
14
  self.config = default
13
- elif verify_config(self.config, default):
15
+ elif self.verify_config(self.config, default):
14
16
  self.save_file()
15
17
 
16
18
  def save_file(self):
@@ -60,26 +62,39 @@ class Config:
60
62
  return len(self.config)
61
63
 
62
64
  def __setitem__(self, key, value):
63
- self.config[key] = value
64
- self.save_file()
65
+ if self.validate(key, value):
66
+ self.config[key] = value
67
+ self.save_file()
65
68
 
66
69
  def __getitem__(self, key):
67
70
  return self.config[key]
68
71
 
69
-
70
- def verify_config(config, default_config):
71
- modified = False
72
-
73
- # Remove entries that do not exist in default_config
74
- for key in list(config.keys()):
75
- if key not in default_config:
76
- del config[key]
77
- modified = True
78
-
79
- # Check entries in default_config
80
- for key, default_value in default_config.items():
81
- if key not in config or type(config[key]) != type(default_value):
82
- config[key] = default_value
83
- modified = True
84
-
85
- return not modified
72
+ def validate(self, key, value):
73
+ if self.validator is not None:
74
+ valid, message = self.validator(key, value)
75
+ if not valid:
76
+ communicate.config_validation.emit(message)
77
+ return False
78
+ return True
79
+
80
+ def verify_config(self, config, default_config):
81
+ modified = False
82
+
83
+ # Remove entries that do not exist in default_config
84
+ for key in list(config.keys()):
85
+ if key not in default_config:
86
+ del config[key]
87
+ modified = True
88
+
89
+ # Check entries in default_config
90
+ for key, default_value in default_config.items():
91
+ if key not in config or type(config[key]) != type(default_value):
92
+ config[key] = default_value
93
+ modified = True
94
+ elif self.validator is not None:
95
+ valid = self.validate(key, self.config[key])
96
+ if not valid:
97
+ config[key] = default_value
98
+ modified = True
99
+
100
+ return not modified
@@ -17,6 +17,7 @@ class Communicate(QObject):
17
17
  screenshot = Signal(np.ndarray, str)
18
18
  update_overlay = Signal()
19
19
  adb_devices: Signal = Signal(bool)
20
+ config_validation: Signal = Signal(str)
20
21
  tab = Signal(str)
21
22
  capture_error = Signal()
22
23
 
@@ -67,6 +67,20 @@ class MainWindow(MSFluentWindow):
67
67
 
68
68
  communicate.capture_error.connect(self.capture_error)
69
69
  communicate.notification.connect(self.show_notification)
70
+ communicate.config_validation.connect(self.config_validation)
71
+
72
+ def config_validation(self, message):
73
+ title = self.tr('Error')
74
+ InfoBar.error(
75
+ title=title,
76
+ content=message,
77
+ orient=Qt.Horizontal,
78
+ isClosable=True,
79
+ position=InfoBarPosition.TOP,
80
+ duration=5000, # won't disappear automatically
81
+ parent=self.window()
82
+ )
83
+ self.tray.showMessage(title, message)
70
84
 
71
85
  def show_notification(self, message, title=None, error=None):
72
86
  bar = InfoBar.error if error else InfoBar.info
@@ -20,10 +20,9 @@ logger = get_logger(__name__)
20
20
 
21
21
  class Screenshot(QObject):
22
22
 
23
- def __init__(self):
23
+ def __init__(self, exit_event):
24
24
  super().__init__()
25
25
  self.queue = []
26
- self.exit_event = ok.gui.ok.exit_event
27
26
  self.time_to_expire = 3
28
27
  self.ui_dict = {}
29
28
  self.color_map = {
@@ -31,10 +30,13 @@ class Screenshot(QObject):
31
30
  "green": QColor(0, 255, 0), # RGB for green
32
31
  "blue": QColor(0, 0, 255) # RGB for blue
33
32
  }
33
+ self.exit_event = exit_event
34
34
  communicate.draw_box.connect(self.draw_box)
35
35
  communicate.screenshot.connect(self.screenshot)
36
36
  self.click_screenshot_folder = get_path_relative_to_exe(ok.gui.ok.config.get("click_screenshots_folder"))
37
37
  self.screenshot_folder = get_path_relative_to_exe(ok.gui.ok.config.get("screenshots_folder"))
38
+ logger.debug(f"init Screenshot {self.screenshot_folder} {self.click_screenshot_folder}")
39
+ print(f"init Screenshot {self.screenshot_folder} {self.screenshot_folder}")
38
40
  if self.click_screenshot_folder is not None or self.screenshot_folder is not None:
39
41
  self.task_queue = queue.Queue()
40
42
  self.exit_event.bind_queue(self.task_queue)
@@ -106,6 +108,7 @@ class Screenshot(QObject):
106
108
  pil_image = self.to_pil_image(frame)
107
109
  if pil_image is None:
108
110
  return
111
+ self.save_pil_image(name + '_original', folder, pil_image)
109
112
  # Ensure no fill
110
113
  draw = ImageDraw.Draw(pil_image)
111
114
 
@@ -127,6 +130,11 @@ class Screenshot(QObject):
127
130
  # Put text
128
131
  draw.text((x, y + height + 8), f"{box.name or key}_{round(box.confidence * 100)}", fill=color,
129
132
  font=self.pil_font)
133
+ self.save_pil_image(name + '_boxed', folder, pil_image)
134
+
135
+ def save_pil_image(self, name, folder, pil_image):
136
+
137
+ logger.debug(f'save_pil_image {name}, {folder}')
130
138
  now = datetime.now()
131
139
 
132
140
  # Convert to string with milliseconds
@@ -142,6 +150,7 @@ class Screenshot(QObject):
142
150
  pil_image.save(os.path.join(folder, f"{time_string}.png"))
143
151
 
144
152
  def stop(self):
153
+ logger.debug(f'stop screenshot')
145
154
  if self.task_queue is not None:
146
155
  self.task_queue.put(None)
147
156
 
@@ -6,20 +6,20 @@ from ok.gui.tasks.LabelAndSwitchButton import LabelAndSwitchButton
6
6
  from ok.gui.tasks.ModifyListItem import ModifyListItem
7
7
 
8
8
 
9
- def config_widget(config, config_desc, config_type, key, value):
10
- the_type = config_type.get(key)
9
+ def config_widget(task, key, value):
10
+ the_type = task.config_type.get(key)
11
11
  if the_type:
12
12
  if the_type['type'] == 'drop_down':
13
- return LabelAndDropDown(config, config_desc, the_type['options'], key)
13
+ return LabelAndDropDown(task, the_type['options'], key)
14
14
  if isinstance(value, bool):
15
- return LabelAndSwitchButton(config, config_desc, key)
15
+ return LabelAndSwitchButton(task, key)
16
16
  elif isinstance(value, list):
17
- return ModifyListItem(config, config_desc, key)
17
+ return ModifyListItem(task, key)
18
18
  elif isinstance(value, int):
19
- return LabelAndSpinBox(config, config_desc, key)
19
+ return LabelAndSpinBox(task, key)
20
20
  elif isinstance(value, float):
21
- return LabelAndDoubleSpinBox(config, config_desc, key)
21
+ return LabelAndDoubleSpinBox(task, key)
22
22
  elif isinstance(value, str):
23
- return LabelAndLineEdit(config, config_desc, key)
23
+ return LabelAndLineEdit(task, key)
24
24
  else:
25
25
  raise ValueError(f"invalid type {type(value)}, value {value}")
@@ -0,0 +1,16 @@
1
+ from ok.gui.tasks.LabelAndWidget import LabelAndWidget
2
+
3
+
4
+ class ConfigLabelAndWidget(LabelAndWidget):
5
+
6
+ def __init__(self, task, key: str):
7
+ desc = None
8
+ self.key = key
9
+ self.task = task
10
+ self.config = task.config
11
+ if task.config_description is not None:
12
+ desc = task.config_description.get(key)
13
+ super().__init__(key, desc)
14
+
15
+ def update_config(self, value):
16
+ self.config[self.key] = value
@@ -5,10 +5,9 @@ from ok.gui.tasks.ConfigLabelAndWidget import ConfigLabelAndWidget
5
5
 
6
6
  class LabelAndDoubleSpinBox(ConfigLabelAndWidget):
7
7
 
8
- def __init__(self, config, config_desc, key: str):
9
- super().__init__(config_desc, key)
8
+ def __init__(self, task, key: str):
9
+ super().__init__(task, key)
10
10
  self.key = key
11
- self.config = config
12
11
  self.spin_box = DoubleSpinBox()
13
12
  self.update_value()
14
13
  self.spin_box.valueChanged.connect(self.value_changed)
@@ -18,4 +17,4 @@ class LabelAndDoubleSpinBox(ConfigLabelAndWidget):
18
17
  self.spin_box.setValue(self.config.get(self.key))
19
18
 
20
19
  def value_changed(self, value):
21
- self.config[self.key] = value
20
+ self.update_config(value)
@@ -5,10 +5,9 @@ from ok.gui.tasks.ConfigLabelAndWidget import ConfigLabelAndWidget
5
5
 
6
6
  class LabelAndDropDown(ConfigLabelAndWidget):
7
7
 
8
- def __init__(self, config, config_desc, options, key: str):
9
- super().__init__(config_desc, key)
8
+ def __init__(self, task, options, key: str):
9
+ super().__init__(task, key)
10
10
  self.key = key
11
- self.config = config
12
11
  self.combo_box = ComboBox()
13
12
  self.combo_box.addItems(options)
14
13
  self.combo_box.setCurrentIndex(find_string_index(options, self.config.get(self.key)))
@@ -17,7 +16,7 @@ class LabelAndDropDown(ConfigLabelAndWidget):
17
16
  self.add_widget(self.combo_box)
18
17
 
19
18
  def text_changed(self, text):
20
- self.config[self.key] = text
19
+ self.update_config(text)
21
20
 
22
21
 
23
22
  def find_string_index(my_list, target_string):
@@ -5,10 +5,9 @@ from ok.gui.tasks.ConfigLabelAndWidget import ConfigLabelAndWidget
5
5
 
6
6
  class LabelAndLineEdit(ConfigLabelAndWidget):
7
7
 
8
- def __init__(self, config, config_desc, key: str):
9
- super().__init__(config_desc, key)
8
+ def __init__(self, task, key: str):
9
+ super().__init__(task, key)
10
10
  self.key = key
11
- self.config = config
12
11
  self.line_edit = LineEdit()
13
12
  self.update_value()
14
13
  self.line_edit.textChanged.connect(self.value_changed)
@@ -18,4 +17,4 @@ class LabelAndLineEdit(ConfigLabelAndWidget):
18
17
  self.line_edit.setText(self.config.get(self.key))
19
18
 
20
19
  def value_changed(self, value):
21
- self.config[self.key] = value
20
+ self.update_config(value)
@@ -5,10 +5,9 @@ from ok.gui.tasks.ConfigLabelAndWidget import ConfigLabelAndWidget
5
5
 
6
6
  class LabelAndSpinBox(ConfigLabelAndWidget):
7
7
 
8
- def __init__(self, config, config_desc, key: str):
9
- super().__init__(config_desc, key)
8
+ def __init__(self, task, key: str):
9
+ super().__init__(task, key)
10
10
  self.key = key
11
- self.config = config
12
11
  self.spin_box = SpinBox()
13
12
  self.spin_box.setFixedWidth(130)
14
13
  self.update_value()
@@ -19,4 +18,4 @@ class LabelAndSpinBox(ConfigLabelAndWidget):
19
18
  self.spin_box.setValue(self.config.get(self.key))
20
19
 
21
20
  def value_changed(self, value):
22
- self.config[self.key] = value
21
+ self.update_config(value)
@@ -5,10 +5,9 @@ from ok.gui.tasks.ConfigLabelAndWidget import ConfigLabelAndWidget
5
5
 
6
6
  class LabelAndSwitchButton(ConfigLabelAndWidget):
7
7
 
8
- def __init__(self, config, config_desc, key: str):
9
- super().__init__(config_desc, key)
8
+ def __init__(self, task, key: str):
9
+ super().__init__(task, key)
10
10
  self.key = key
11
- self.config = config
12
11
  self.switch_button = SwitchButton()
13
12
  self.switch_button.setOnText(self.tr('Yes'))
14
13
  self.switch_button.setOffText(self.tr('No'))
@@ -20,4 +19,4 @@ class LabelAndSwitchButton(ConfigLabelAndWidget):
20
19
  self.switch_button.setChecked(self.config.get(self.key))
21
20
 
22
21
  def check_changed(self, checked):
23
- self.config[self.key] = checked
22
+ self.update_config(checked)
@@ -8,10 +8,8 @@ from ok.gui.widget.UpdateConfigWidgetItem import value_to_string
8
8
 
9
9
  class ModifyListItem(ConfigLabelAndWidget):
10
10
 
11
- def __init__(self, config, config_desc, key: str):
12
- super().__init__(config_desc, key)
13
- self.key = key
14
- self.config = config
11
+ def __init__(self, task, key: str):
12
+ super().__init__(task, key)
15
13
  self.switch_button = PushButton(self.tr('Modify'))
16
14
  self.switch_button.clicked.connect(self.clicked)
17
15
  self.list_text = QLabel("")
@@ -20,7 +18,15 @@ class ModifyListItem(ConfigLabelAndWidget):
20
18
  self.add_widget(self.switch_button)
21
19
 
22
20
  def update_value(self):
23
- self.list_text.setText(value_to_string(self.config.get(self.key)))
21
+ items = self.config.get(self.key)
22
+ total_length = sum(len(item) for item in items)
23
+
24
+ if total_length > 30:
25
+ display_text = "\n".join(items)
26
+ else:
27
+ display_text = value_to_string(items)
28
+
29
+ self.list_text.setText(display_text)
24
30
 
25
31
  def clicked(self):
26
32
  dialog = ModifyListDialog(self.config.get(self.key), self.window())
@@ -28,5 +34,5 @@ class ModifyListItem(ConfigLabelAndWidget):
28
34
  dialog.exec()
29
35
 
30
36
  def list_modified(self, the_list):
31
- self.config[self.key] = the_list
37
+ self.update_config(the_list)
32
38
  self.update_value()
@@ -61,7 +61,7 @@ class TaskCard(ExpandSettingCard):
61
61
  self.task.disable()
62
62
 
63
63
  def __addConfig(self, key: str, value):
64
- widget = config_widget(self.task.config, self.task.config_description, self.task.config_type, key, value)
64
+ widget = config_widget(self.task, key, value)
65
65
  self.config_widgets.append(widget)
66
66
  self.viewLayout.addWidget(widget)
67
67
  self._adjustViewSize()
@@ -41,6 +41,7 @@ class SaveMethodBase:
41
41
  print("Thread exiting")
42
42
 
43
43
  def stop(self):
44
+ print("SaveMethodBase stop")
44
45
  self.exit_event.set()
45
46
 
46
47
  def wait_until_done(self):
@@ -97,7 +97,17 @@ class BaseTask(ExecutorOperation):
97
97
  self.info[key] = self.info.get(key, 0) + count
98
98
 
99
99
  def load_config(self, folder):
100
- self.config = Config(self.default_config, folder, self.__class__.__name__)
100
+ self.config = Config(self.default_config, folder, self.__class__.__name__, self.validate)
101
+
102
+ def validate(self, key, value):
103
+ message = self.validate_config(key, value)
104
+ if message:
105
+ return False, message
106
+ else:
107
+ return True, None
108
+
109
+ def validate_config(self, key, value):
110
+ pass
101
111
 
102
112
  def enable(self):
103
113
  if not self._enabled:
@@ -78,7 +78,12 @@ class ExecutorOperation:
78
78
  self.click_box(to_click, relative_x, relative_y)
79
79
  return to_click
80
80
 
81
- def box_of_screen(self, x, y, width, height, name=None):
81
+ def box_of_screen(self, x, y, width=0, height=0, to_x=1, to_y=1, name=None):
82
+ if width == 0:
83
+ width = to_x - x
84
+ if height == 0:
85
+ height = to_y - y
86
+
82
87
  if name is None:
83
88
  name = f"{x} {y} {width} {height}"
84
89
  return Box(int(x * self.executor.method.width), int(y * self.executor.method.height),
@@ -305,6 +305,7 @@ class TaskExecutor:
305
305
  return self.current_scene
306
306
 
307
307
  def stop(self):
308
+ logger.info('stop')
308
309
  self.exit_event.set()
309
310
 
310
311
  def wait_until_done(self):
@@ -1,5 +1,9 @@
1
1
  import threading
2
2
 
3
+ from ok.logging.Logger import get_logger
4
+
5
+ logger = get_logger(__name__)
6
+
3
7
 
4
8
  class ExitEvent(threading.Event):
5
9
  queues = set()
@@ -9,5 +13,6 @@ class ExitEvent(threading.Event):
9
13
 
10
14
  def set(self):
11
15
  super(ExitEvent, self).set()
16
+ logger.debug(f"ExitEvent set event empty queues")
12
17
  for queue in self.queues:
13
18
  queue.put(None)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ok-script
3
- Version: 0.0.40
3
+ Version: 0.0.41
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
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="ok-script",
8
- version="0.0.40",
8
+ version="0.0.41",
9
9
  author="ok-oldking",
10
10
  author_email="firedcto@gmail.com",
11
11
  description="Automation with Computer Vision for Python",
@@ -1,10 +0,0 @@
1
- from ok.gui.tasks.LabelAndWidget import LabelAndWidget
2
-
3
-
4
- class ConfigLabelAndWidget(LabelAndWidget):
5
-
6
- def __init__(self, config_desc, key: str):
7
- desc = None
8
- if config_desc is not None:
9
- desc = config_desc.get(key)
10
- super().__init__(key, desc)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes