ok-script 0.0.84__tar.gz → 0.0.86__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 (184) hide show
  1. {ok-script-0.0.84 → ok-script-0.0.86}/PKG-INFO +1 -1
  2. {ok-script-0.0.84 → ok-script-0.0.86}/ok/capture/HwndWindow.py +18 -15
  3. {ok-script-0.0.84 → ok-script-0.0.86}/ok/capture/adb/DeviceManager.py +20 -23
  4. {ok-script-0.0.84 → ok-script-0.0.86}/ok/config/Config.py +3 -1
  5. {ok-script-0.0.84 → ok-script-0.0.86}/ok/feature/FindFeature.py +2 -2
  6. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/App.py +6 -0
  7. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/MainWindow.py +3 -6
  8. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/debug/DebugTab.py +0 -3
  9. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/debug/FrameWidget.py +4 -6
  10. ok-script-0.0.86/ok/gui/debug/LogWindow.py +189 -0
  11. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/debug/Screenshot.py +0 -1
  12. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/tasks/TaskCard.py +5 -5
  13. {ok-script-0.0.84 → ok-script-0.0.86}/ok/interaction/BaseInteraction.py +3 -3
  14. {ok-script-0.0.84 → ok-script-0.0.86}/ok/ocr/OCR.py +1 -1
  15. {ok-script-0.0.84 → ok-script-0.0.86}/ok/task/BaseTask.py +28 -9
  16. {ok-script-0.0.84 → ok-script-0.0.86}/ok/task/TaskExecutor.py +10 -7
  17. {ok-script-0.0.84 → ok-script-0.0.86}/ok/task/TriggerTask.py +1 -1
  18. ok-script-0.0.86/ok/util/list.py +9 -0
  19. {ok-script-0.0.84 → ok-script-0.0.86}/ok_script.egg-info/PKG-INFO +1 -1
  20. {ok-script-0.0.84 → ok-script-0.0.86}/ok_script.egg-info/SOURCES.txt +1 -2
  21. {ok-script-0.0.84 → ok-script-0.0.86}/setup.py +1 -1
  22. ok-script-0.0.84/ok/gui/debug/LoggerWidget.py +0 -77
  23. ok-script-0.0.84/ok/task/OneTimeTask.py +0 -35
  24. ok-script-0.0.84/ok/util/list.py +0 -2
  25. {ok-script-0.0.84 → ok-script-0.0.86}/README.md +0 -0
  26. {ok-script-0.0.84 → ok-script-0.0.86}/ok/OK.py +0 -0
  27. {ok-script-0.0.84 → ok-script-0.0.86}/ok/__init__.py +0 -0
  28. {ok-script-0.0.84 → ok-script-0.0.86}/ok/alas/__init__.py +0 -0
  29. {ok-script-0.0.84 → ok-script-0.0.86}/ok/alas/emulator_base.py +0 -0
  30. {ok-script-0.0.84 → ok-script-0.0.86}/ok/alas/emulator_windows.py +0 -0
  31. {ok-script-0.0.84 → ok-script-0.0.86}/ok/alas/platform_base.py +0 -0
  32. {ok-script-0.0.84 → ok-script-0.0.86}/ok/alas/platform_windows.py +0 -0
  33. {ok-script-0.0.84 → ok-script-0.0.86}/ok/alas/utils.py +0 -0
  34. {ok-script-0.0.84 → ok-script-0.0.86}/ok/capture/BaseCaptureMethod.py +0 -0
  35. {ok-script-0.0.84 → ok-script-0.0.86}/ok/capture/__init__.py +0 -0
  36. {ok-script-0.0.84 → ok-script-0.0.86}/ok/capture/adb/ADBCaptureMethod.py +0 -0
  37. {ok-script-0.0.84 → ok-script-0.0.86}/ok/capture/adb/WindowsCaptureFactory.py +0 -0
  38. {ok-script-0.0.84 → ok-script-0.0.86}/ok/capture/adb/__init__.py +0 -0
  39. {ok-script-0.0.84 → ok-script-0.0.86}/ok/capture/adb/bin/__init__.py +0 -0
  40. {ok-script-0.0.84 → ok-script-0.0.86}/ok/capture/image/ImageCaptureMethod.py +0 -0
  41. {ok-script-0.0.84 → ok-script-0.0.86}/ok/capture/image/__init__.py +0 -0
  42. {ok-script-0.0.84 → ok-script-0.0.86}/ok/capture/windows/BaseWindowsCaptureMethod.py +0 -0
  43. {ok-script-0.0.84 → ok-script-0.0.86}/ok/capture/windows/BitBltCaptureMethod.py +0 -0
  44. {ok-script-0.0.84 → ok-script-0.0.86}/ok/capture/windows/DesktopDuplicationCaptureMethod.py +0 -0
  45. {ok-script-0.0.84 → ok-script-0.0.86}/ok/capture/windows/WindowsGraphicsCaptureMethod.py +0 -0
  46. {ok-script-0.0.84 → ok-script-0.0.86}/ok/capture/windows/__init__.py +0 -0
  47. {ok-script-0.0.84 → ok-script-0.0.86}/ok/capture/windows/d3d11.py +0 -0
  48. {ok-script-0.0.84 → ok-script-0.0.86}/ok/capture/windows/dump.py +0 -0
  49. {ok-script-0.0.84 → ok-script-0.0.86}/ok/capture/windows/utils.py +0 -0
  50. {ok-script-0.0.84 → ok-script-0.0.86}/ok/capture/windows/window.py +0 -0
  51. {ok-script-0.0.84 → ok-script-0.0.86}/ok/color/Color.py +0 -0
  52. {ok-script-0.0.84 → ok-script-0.0.86}/ok/color/__init__.py +0 -0
  53. {ok-script-0.0.84 → ok-script-0.0.86}/ok/config/InfoDict.py +0 -0
  54. {ok-script-0.0.84 → ok-script-0.0.86}/ok/config/__init__.py +0 -0
  55. {ok-script-0.0.84 → ok-script-0.0.86}/ok/feature/Box.py +0 -0
  56. {ok-script-0.0.84 → ok-script-0.0.86}/ok/feature/Feature.py +0 -0
  57. {ok-script-0.0.84 → ok-script-0.0.86}/ok/feature/FeatureSet.py +0 -0
  58. {ok-script-0.0.84 → ok-script-0.0.86}/ok/feature/__init__.py +0 -0
  59. {ok-script-0.0.84 → ok-script-0.0.86}/ok/firebase/Analytics.py +0 -0
  60. {ok-script-0.0.84 → ok-script-0.0.86}/ok/firebase/__init__.py +0 -0
  61. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/Communicate.py +0 -0
  62. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/MessageWindow.py +0 -0
  63. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/StartController.py +0 -0
  64. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/TabTitles.py +0 -0
  65. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/__init__.py +0 -0
  66. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/about/AboutTab.py +0 -0
  67. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/about/HttpTextEdit.py +0 -0
  68. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/about/VersionCard.py +0 -0
  69. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/about/__init__.py +0 -0
  70. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/common/OKIcon.py +0 -0
  71. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/common/__init__.py +0 -0
  72. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/common/config.py +0 -0
  73. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/common/style_sheet.py +0 -0
  74. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/debug/AspectRatioWidget.py +0 -0
  75. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/debug/InfoWidget.py +0 -0
  76. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/debug/__init__.py +0 -0
  77. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/i18n/__init__.py +0 -0
  78. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/i18n/path.py +0 -0
  79. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/i18n/update.py +0 -0
  80. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/icon/__init__.py +0 -0
  81. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/icon/icon.py +0 -0
  82. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/overlay/OverlayWindow.py +0 -0
  83. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/overlay/__init__.py +0 -0
  84. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/qss/__init__.py +0 -0
  85. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/resources.py +0 -0
  86. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/settings/SettingTab.py +0 -0
  87. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/settings/__init__.py +0 -0
  88. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/start/SelectCaptureListView.py +0 -0
  89. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/start/StartCard.py +0 -0
  90. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/start/StartTab.py +0 -0
  91. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/start/__init__.py +0 -0
  92. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/tasks/ConfigItemFactory.py +0 -0
  93. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/tasks/ConfigLabelAndWidget.py +0 -0
  94. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/tasks/LabelAndDoubleSpinBox.py +0 -0
  95. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/tasks/LabelAndDropDown.py +0 -0
  96. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/tasks/LabelAndLineEdit.py +0 -0
  97. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/tasks/LabelAndList.py +0 -0
  98. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/tasks/LabelAndSpinBox.py +0 -0
  99. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/tasks/LabelAndSwitchButton.py +0 -0
  100. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/tasks/LabelAndWidget.py +0 -0
  101. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/tasks/ModifyListDialog.py +0 -0
  102. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/tasks/ModifyListItem.py +0 -0
  103. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/tasks/OneTimeTaskTab.py +0 -0
  104. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/tasks/StartButton.py +0 -0
  105. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/tasks/TaskOpButton.py +0 -0
  106. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/tasks/TooltipTableWidget.py +0 -0
  107. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/tasks/TriggerTaskTab.py +0 -0
  108. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/tasks/__init__.py +0 -0
  109. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/util/Alert.py +0 -0
  110. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/util/InitWorker.py +0 -0
  111. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/util/__init__.py +0 -0
  112. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/widget/Card.py +0 -0
  113. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/widget/EmptyCard.py +0 -0
  114. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/widget/FramelessDialog.py +0 -0
  115. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/widget/ListTableWidgetItem.py +0 -0
  116. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/widget/NumericTableWidgetItem.py +0 -0
  117. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/widget/StartLoadingDialog.py +0 -0
  118. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/widget/StatusBar.py +0 -0
  119. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/widget/Tab.py +0 -0
  120. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/widget/TabWidget.py +0 -0
  121. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/widget/UpdateConfigWidgetItem.py +0 -0
  122. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/widget/YesNonWidgetItem.py +0 -0
  123. {ok-script-0.0.84 → ok-script-0.0.86}/ok/gui/widget/__init__.py +0 -0
  124. {ok-script-0.0.84 → ok-script-0.0.86}/ok/interaction/ADBInteraction.py +0 -0
  125. {ok-script-0.0.84 → ok-script-0.0.86}/ok/interaction/DoNothingInteraction.py +0 -0
  126. {ok-script-0.0.84 → ok-script-0.0.86}/ok/interaction/Win32Interaction.py +0 -0
  127. {ok-script-0.0.84 → ok-script-0.0.86}/ok/interaction/__init__.py +0 -0
  128. {ok-script-0.0.84 → ok-script-0.0.86}/ok/logging/Logger.py +0 -0
  129. {ok-script-0.0.84 → ok-script-0.0.86}/ok/logging/__init__.py +0 -0
  130. {ok-script-0.0.84 → ok-script-0.0.86}/ok/ocr/__init__.py +0 -0
  131. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/Windows/Foundation/Collections.py +0 -0
  132. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/Windows/Foundation/__init__.py +0 -0
  133. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/Windows/Globalization/__init__.py +0 -0
  134. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/Windows/Graphics/Capture/__init__.py +0 -0
  135. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/Windows/Graphics/DirectX/Direct3D11/__init__.py +0 -0
  136. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/Windows/Graphics/DirectX/__init__.py +0 -0
  137. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/Windows/Graphics/Imaging/__init__.py +0 -0
  138. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/Windows/Graphics/__init__.py +0 -0
  139. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/Windows/Media/Ocr/__init__.py +0 -0
  140. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/Windows/Media/__init__.py +0 -0
  141. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/Windows/Security/Cryptography/__init__.py +0 -0
  142. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/Windows/Security/__init__.py +0 -0
  143. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/Windows/Storage/Streams/__init__.py +0 -0
  144. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/Windows/Storage/__init__.py +0 -0
  145. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/Windows/__init__.py +0 -0
  146. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/__init__.py +0 -0
  147. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/delegate.py +0 -0
  148. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/export.py +0 -0
  149. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/idldsl.py +0 -0
  150. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/inspectable.py +0 -0
  151. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/roapi.py +0 -0
  152. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/types.py +0 -0
  153. {ok-script-0.0.84 → ok-script-0.0.86}/ok/rotypes/winstring.py +0 -0
  154. {ok-script-0.0.84 → ok-script-0.0.86}/ok/save/BlackBarProcessor.py +0 -0
  155. {ok-script-0.0.84 → ok-script-0.0.86}/ok/save/PostProcessor.py +0 -0
  156. {ok-script-0.0.84 → ok-script-0.0.86}/ok/save/SaveByInterval.py +0 -0
  157. {ok-script-0.0.84 → ok-script-0.0.86}/ok/save/SaveByKeyPress.py +0 -0
  158. {ok-script-0.0.84 → ok-script-0.0.86}/ok/save/SaveMethodBase.py +0 -0
  159. {ok-script-0.0.84 → ok-script-0.0.86}/ok/save/__init__.py +0 -0
  160. {ok-script-0.0.84 → ok-script-0.0.86}/ok/scene/FeatureScene.py +0 -0
  161. {ok-script-0.0.84 → ok-script-0.0.86}/ok/scene/Scene.py +0 -0
  162. {ok-script-0.0.84 → ok-script-0.0.86}/ok/scene/__init__.py +0 -0
  163. {ok-script-0.0.84 → ok-script-0.0.86}/ok/stats/StreamStats.py +0 -0
  164. {ok-script-0.0.84 → ok-script-0.0.86}/ok/stats/__init__.py +0 -0
  165. {ok-script-0.0.84 → ok-script-0.0.86}/ok/task/ExecutorOperation.py +0 -0
  166. {ok-script-0.0.84 → ok-script-0.0.86}/ok/task/__init__.py +0 -0
  167. {ok-script-0.0.84 → ok-script-0.0.86}/ok/update/GithubMultiDownloader.py +0 -0
  168. {ok-script-0.0.84 → ok-script-0.0.86}/ok/update/Updater.py +0 -0
  169. {ok-script-0.0.84 → ok-script-0.0.86}/ok/update/__init__.py +0 -0
  170. {ok-script-0.0.84 → ok-script-0.0.86}/ok/update/gen_md5.py +0 -0
  171. {ok-script-0.0.84 → ok-script-0.0.86}/ok/util/Handler.py +0 -0
  172. {ok-script-0.0.84 → ok-script-0.0.86}/ok/util/__init__.py +0 -0
  173. {ok-script-0.0.84 → ok-script-0.0.86}/ok/util/exit_event.py +0 -0
  174. {ok-script-0.0.84 → ok-script-0.0.86}/ok/util/json.py +0 -0
  175. {ok-script-0.0.84 → ok-script-0.0.86}/ok/util/path.py +0 -0
  176. {ok-script-0.0.84 → ok-script-0.0.86}/ok/util/thread.py +0 -0
  177. {ok-script-0.0.84 → ok-script-0.0.86}/ok/util/win32_process.py +0 -0
  178. {ok-script-0.0.84 → ok-script-0.0.86}/ok/util/yaml.py +0 -0
  179. {ok-script-0.0.84 → ok-script-0.0.86}/ok_script.egg-info/dependency_links.txt +0 -0
  180. {ok-script-0.0.84 → ok-script-0.0.86}/ok_script.egg-info/requires.txt +0 -0
  181. {ok-script-0.0.84 → ok-script-0.0.86}/ok_script.egg-info/top_level.txt +0 -0
  182. {ok-script-0.0.84 → ok-script-0.0.86}/setup.cfg +0 -0
  183. {ok-script-0.0.84 → ok-script-0.0.86}/tests/__init__.py +0 -0
  184. {ok-script-0.0.84 → ok-script-0.0.86}/tests/test_updater.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ok-script
3
- Version: 0.0.84
3
+ Version: 0.0.86
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
@@ -42,31 +42,23 @@ class HwndWindow:
42
42
  real_x_offset = 0
43
43
  real_y_offset = 0
44
44
 
45
- def __init__(self, exit_event, title, exe_name=None, frame_width=0, frame_height=0):
45
+ def __init__(self, exit_event, title, exe_name=None, frame_width=0, frame_height=0, player_id=-1):
46
46
  super().__init__()
47
47
  self.app_exit_event = exit_event
48
48
  self.exe_name = exe_name
49
49
  self.title = title
50
50
  self.stop_event = threading.Event()
51
51
  self.visible = False
52
+ self.player_id = player_id
52
53
  self.update_window(title, exe_name, frame_width, frame_height)
53
54
  self.thread = threading.Thread(target=self.update_window_size, name="update_window_size")
54
55
  self.thread.start()
55
56
 
56
- def update_title_and_exe(self, title, exe):
57
- self.title = title
58
- self.exe_name = exe
59
- self.hwnd = None
60
- self.visible = False
61
- self.exists = False
62
- self.width = 0
63
- self.height = 0
64
- self.do_update_window_size()
65
-
66
57
  def stop(self):
67
58
  self.stop_event.set()
68
59
 
69
- def update_window(self, title, exe_name, frame_width, frame_height):
60
+ def update_window(self, title, exe_name, frame_width, frame_height, player_id=-1):
61
+ self.player_id = player_id
70
62
  self.title = title
71
63
  self.exe_name = exe_name
72
64
  self.update_frame_size(frame_width, frame_height)
@@ -100,7 +92,7 @@ class HwndWindow:
100
92
  name, self.hwnd, self.exe_full_path, self.real_x_offset, self.real_y_offset, self.real_width, self.real_height = find_hwnd(
101
93
  self.title,
102
94
  self.exe_name,
103
- self.frame_width, self.frame_height)
95
+ self.frame_width, self.frame_height, player_id=self.player_id)
104
96
  self.exists = self.hwnd is not None
105
97
  if self.hwnd is not None:
106
98
  self.exists = win32gui.IsWindow(self.hwnd)
@@ -168,6 +160,8 @@ def find_hwnd(title, exe_name, frame_width, frame_height, player_id=-1):
168
160
  elif not re.search(title, text):
169
161
  return True
170
162
  name, full_path, cmdline = get_exe_by_hwnd(hwnd)
163
+ if not name:
164
+ return True
171
165
  x, y, border, title_height, width, height, scaling, ext_left_bounds, ext_top_bounds = get_window_bounds(
172
166
  hwnd)
173
167
  ret = (hwnd, full_path, width, height, x, y, text)
@@ -210,6 +204,12 @@ def get_player_id_from_cmdline(cmdline):
210
204
  if i != 0:
211
205
  if cmdline[i].isdigit():
212
206
  return int(cmdline[i])
207
+ for i in range(len(cmdline)):
208
+ if i != 0:
209
+ value = re.search(r'index=(\d+)', cmdline[i])
210
+ # Return the value if it exists, otherwise return None
211
+ if value is not None:
212
+ return int(value.group(1))
213
213
  return 0
214
214
 
215
215
 
@@ -248,8 +248,11 @@ def get_exe_by_hwnd(hwnd):
248
248
  _, pid = win32process.GetWindowThreadProcessId(hwnd)
249
249
 
250
250
  # Get the process name and executable path
251
- process = psutil.Process(pid)
252
- return process.name(), process.exe(), process.cmdline()
251
+ if pid > 0:
252
+ process = psutil.Process(pid)
253
+ return process.name(), process.exe(), process.cmdline()
254
+ else:
255
+ return None, None, None
253
256
 
254
257
 
255
258
  if __name__ == '__main__':
@@ -1,4 +1,4 @@
1
- from adbutils import AdbTimeout
1
+ from adbutils import AdbTimeout, AdbError
2
2
 
3
3
  from ok.alas.platform_windows import get_emulator_exe
4
4
  from ok.capture.HwndWindow import HwndWindow, find_hwnd
@@ -53,27 +53,25 @@ class DeviceManager:
53
53
  logger.debug(f'connect adb')
54
54
  return self._adb
55
55
 
56
- def adb_connect(self, addr):
56
+ def adb_connect(self, addr, try_connect=True):
57
57
  try:
58
- for info in self.adb.list():
58
+ for device in self.adb.device_list():
59
59
  if self.exit_event.is_set():
60
60
  logger.error(f"adb_connect exit_event is set")
61
61
  return None
62
- if info.serial == addr:
63
- if info.state == 'offline':
62
+ if device.serial == addr:
63
+ if device.info['state'] == 'offline':
64
64
  logger.debug(f'adb_connect offline disconnect first {addr}')
65
65
  self.adb.disconnect(addr)
66
66
  else:
67
67
  logger.debug(f'adb_connect already connected {addr}')
68
- return self.adb.device(addr)
69
- self.adb.connect(addr, timeout=5)
70
- device = self.adb.device(addr)
71
- logger.debug(f'adb_connect {addr} device {device}')
72
- return device
68
+ return device
69
+ if try_connect:
70
+ self.adb.connect(addr, timeout=5)
71
+ logger.debug(f'adb_connect {addr}')
72
+ return self.adb_connect(addr, try_connect=False)
73
73
  except AdbTimeout as e:
74
74
  logger.error(f"adb connect error try kill server {addr}", e)
75
- # self.adb.server_kill()
76
- # self._adb = None
77
75
  except Exception as e:
78
76
  logger.error(f"adb connect error return none {addr}", e)
79
77
 
@@ -101,9 +99,7 @@ class DeviceManager:
101
99
 
102
100
  def do_refresh(self, current=False):
103
101
  self.update_pc_device()
104
-
105
102
  self.refresh_emulators(current)
106
-
107
103
  self.refresh_phones(current)
108
104
 
109
105
  if self.exit_event.is_set():
@@ -131,7 +127,7 @@ class DeviceManager:
131
127
  width, height = self.get_resolution(adb_device)
132
128
  logger.debug(f'refresh_phones found an phone {adb_device}')
133
129
  phone_device = {"address": adb_device.serial, "device": "adb", "connected": True, "imei": imei,
134
- "nick": adb_device.prop.model or imei,
130
+ "nick": adb_device.prop.model or imei, "player_id": -1,
135
131
  "resolution": f'{width}x{height}'}
136
132
  self.device_dict[imei] = phone_device
137
133
 
@@ -147,13 +143,13 @@ class DeviceManager:
147
143
  logger.debug(f"refresh current only skip others {preferred['imei']} != {emulator.name}")
148
144
  break
149
145
  adb_device = self.adb_connect(emulator.serial)
150
- width, height = self.get_resolution(adb_device)
146
+ width, height = self.get_resolution(adb_device) if adb_device is not None else 0, 0
151
147
  name, hwnd, full_path, x, y, width, height = find_hwnd(None,
152
148
  emulator.path, width, height, emulator.player_id)
153
149
  connected = adb_device is not None and name is not None
154
150
  emulator_device = {"address": emulator.serial, "device": "adb",
155
151
  "full_path": emulator.path, "connected": connected,
156
- "imei": emulator.name,
152
+ "imei": emulator.name, "player_id": emulator.player_id,
157
153
  "nick": name or emulator.name, "emulator": emulator}
158
154
  if adb_device is not None:
159
155
  emulator_device["resolution"] = f"{width}x{height}"
@@ -236,11 +232,11 @@ class DeviceManager:
236
232
  preferred = self.get_preferred_device()
237
233
  return preferred.get('hwnd')
238
234
 
239
- def ensure_hwnd(self, title, exe, frame_width=0, frame_height=0):
235
+ def ensure_hwnd(self, title, exe, frame_width=0, frame_height=0, player_id=-1):
240
236
  if self.hwnd is None:
241
- self.hwnd = HwndWindow(self.exit_event, title, exe, frame_width, frame_height)
237
+ self.hwnd = HwndWindow(self.exit_event, title, exe, frame_width, frame_height, player_id)
242
238
  else:
243
- self.hwnd.update_window(title, exe, frame_width, frame_height)
239
+ self.hwnd.update_window(title, exe, frame_width, frame_height, player_id)
244
240
 
245
241
  def use_windows_capture(self, override_config=None, require_bg=False, use_bit_blt_only=False):
246
242
  if not override_config:
@@ -271,7 +267,7 @@ class DeviceManager:
271
267
  else:
272
268
  width, height = self.get_resolution()
273
269
  if self.config.get('capture') == "windows":
274
- self.ensure_hwnd(None, preferred.get('full_path'), width, height)
270
+ self.ensure_hwnd(None, preferred.get('full_path'), width, height, preferred['player_id'])
275
271
  self.use_windows_capture({'can_bit_blt': True}, require_bg=True, use_bit_blt_only=True)
276
272
  else:
277
273
  if not isinstance(self.capture_method, ADBCaptureMethod):
@@ -281,7 +277,7 @@ class DeviceManager:
281
277
  self.capture_method = ADBCaptureMethod(self, self.exit_event, width=width,
282
278
  height=height)
283
279
  if self.debug and preferred.get('full_path'):
284
- self.ensure_hwnd(None, preferred.get('full_path'), width, height)
280
+ self.ensure_hwnd(None, preferred.get('full_path'), width, height, preferred['player_id'])
285
281
  elif self.hwnd is not None:
286
282
  self.hwnd.stop()
287
283
  self.hwnd = None
@@ -341,12 +337,13 @@ class DeviceManager:
341
337
  if device is not None:
342
338
  try:
343
339
  return device.shell(*args, **kwargs)
340
+ except AdbError as e:
341
+ logger.debug(f'shell adb error {args} {e}')
344
342
  except Exception as e:
345
343
  addr = self.get_preferred_device()['address']
346
344
  self.refresh_emulators()
347
345
  new_addr = self.get_preferred_device()['address']
348
346
  logger.error(f"shell_wrapper error occurred, try refresh_emulators {addr} {new_addr}", e)
349
- return None
350
347
  else:
351
348
  raise Exception('Device is none')
352
349
 
@@ -78,8 +78,10 @@ class Config(dict):
78
78
 
79
79
  def __setitem__(self, key, value):
80
80
  if self.validate(key, value):
81
+ old_value = self.get(key)
81
82
  super().__setitem__(key, value)
82
- self.save_file()
83
+ if old_value != value:
84
+ self.save_file()
83
85
 
84
86
  def __getitem__(self, key):
85
87
  try:
@@ -44,9 +44,9 @@ class FindFeature:
44
44
  return False
45
45
 
46
46
  def find_one(self, feature_name, horizontal_variance=0, vertical_variance=0, threshold=0,
47
- use_gray_scale=False) -> Box:
47
+ use_gray_scale=False, box=None) -> Box:
48
48
  boxes = self.find_feature(feature_name, horizontal_variance, vertical_variance, threshold,
49
- use_gray_scale=use_gray_scale)
49
+ use_gray_scale=use_gray_scale, box=box)
50
50
  if len(boxes) > 0:
51
51
  if len(boxes) > 1:
52
52
  print(f"find_one:found {feature_name} too many {len(boxes)}", file=sys.stderr)
@@ -13,6 +13,7 @@ from ok.gui.Communicate import communicate
13
13
  from ok.gui.MainWindow import MainWindow
14
14
  from ok.gui.MessageWindow import MessageWindow
15
15
  from ok.gui.StartController import StartController
16
+ from ok.gui.debug.LogWindow import LogWindow
16
17
  from ok.gui.i18n.path import i18n_path
17
18
  from ok.gui.overlay.OverlayWindow import OverlayWindow
18
19
  from ok.logging.Logger import get_logger
@@ -47,6 +48,7 @@ class App:
47
48
  self.loading_window = None
48
49
  self.overlay_window = None
49
50
  self.main_window = None
51
+ self.log_window = None
50
52
  self.exit_event = exit_event
51
53
  self.icon = QIcon(self.config.get('gui_icon') or ":/icon/icon.ico")
52
54
  if self.config.get('analytics'):
@@ -109,6 +111,10 @@ class App:
109
111
  self.main_window.show()
110
112
  self.main_window.raise_()
111
113
  self.main_window.activateWindow()
114
+ if self.config.get('debug'):
115
+ self.log_window = LogWindow(self.config)
116
+ self.log_window.show()
117
+ logger.debug('showing log_window')
112
118
 
113
119
  def size_relative_to_screen(self, width, height):
114
120
  screen = self.app.primaryScreen()
@@ -43,10 +43,7 @@ class MainWindow(MSFluentWindow):
43
43
  if self.first_tab is None:
44
44
  self.first_tab = self.trigger_tab
45
45
  self.addSubInterface(self.trigger_tab, FluentIcon.ROBOT, self.tr('Triggers'))
46
- # if debug:
47
- # debug_tab = DebugTab()
48
- # self.addSubInterface(debug_tab, FluentIcon.COMMAND_PROMPT, self.tr('Debug'))
49
- # ... Add other tabs similarly
46
+
50
47
  self.addSubInterface(self.start_tab, FluentIcon.PLAY, self.tr('Capture'))
51
48
 
52
49
  if debug:
@@ -77,8 +74,8 @@ class MainWindow(MSFluentWindow):
77
74
  self.tray.setContextMenu(menu)
78
75
  self.tray.show()
79
76
 
80
- if ok.gui.device_manager.get_preferred_device() is not None and self.onetime_tab is not None:
81
- self.switchTo(self.onetime_tab)
77
+ if ok.gui.device_manager.config.get("preferred") is None or self.onetime_tab is None:
78
+ self.switchTo(self.start_tab)
82
79
 
83
80
  communicate.capture_error.connect(self.capture_error)
84
81
  communicate.notification.connect(self.show_notification)
@@ -49,9 +49,6 @@ class DebugTab(Tab):
49
49
  capture_button.clicked.connect(lambda: self.handler.post(self.capture))
50
50
  layout.addWidget(capture_button)
51
51
 
52
- # self.shortcut = QShortcut(QKeySequence("Ctrl+Alt+S"), self)
53
- # self.shortcut.activated.connect(lambda: self.handler.post(self.capture))
54
-
55
52
  ocr_button = PushButton("OCR")
56
53
  ocr_button.clicked.connect(lambda: self.handler.post(self.ocr))
57
54
  layout.addWidget(ocr_button)
@@ -6,7 +6,6 @@ from PySide6.QtGui import QPainter, QColor, QPen, QFont, QGuiApplication
6
6
  from PySide6.QtWidgets import QWidget
7
7
 
8
8
  import ok.gui
9
- from ok.gui.Communicate import communicate
10
9
  from ok.logging.Logger import get_logger
11
10
 
12
11
  logger = get_logger(__name__)
@@ -15,10 +14,8 @@ logger = get_logger(__name__)
15
14
  class FrameWidget(QWidget):
16
15
  def __init__(self):
17
16
  super(FrameWidget, self).__init__()
18
- self._visible = True
19
17
  self._mouse_position = QPoint(0, 0)
20
18
  self.setMouseTracking(True)
21
- communicate.update_overlay.connect(self.update)
22
19
  # Start a timer to update mouse position using Windows API
23
20
  self.timer = QTimer(self)
24
21
  self.timer.timeout.connect(self.update_mouse_position)
@@ -27,13 +24,14 @@ class FrameWidget(QWidget):
27
24
  self.mouse_font.setPointSize(10) # Adjust the size as needed
28
25
  screen = QGuiApplication.primaryScreen()
29
26
  self.scaling = screen.devicePixelRatio()
30
- communicate.update_overlay.connect(self.update)
31
27
 
32
28
  def update_mouse_position(self):
33
29
  try:
30
+ if not self.isVisible():
31
+ return
34
32
  x, y = win32api.GetCursorPos()
35
33
  relative = self.mapFromGlobal(QPoint(x / self.scaling, y / self.scaling))
36
- if self._mouse_position != relative and relative.x() > 0 and relative.y() > 0 and self._visible:
34
+ if self._mouse_position != relative and relative.x() > 0 and relative.y() > 0:
37
35
  self._mouse_position = relative
38
36
  self.update()
39
37
  except Exception as e:
@@ -45,7 +43,7 @@ class FrameWidget(QWidget):
45
43
  return self.width() / ok.gui.device_manager.width
46
44
 
47
45
  def paintEvent(self, event):
48
- if not self._visible:
46
+ if not self.isVisible():
49
47
  return
50
48
  painter = QPainter(self)
51
49
  self.paint_border(painter)
@@ -0,0 +1,189 @@
1
+ from PySide6.QtCore import Qt, QAbstractListModel, QModelIndex, QPoint, Signal
2
+ from PySide6.QtGui import QColor
3
+ from PySide6.QtWidgets import QVBoxLayout, QListView, QLineEdit, QHBoxLayout, QComboBox, QAbstractItemView, QWidget, \
4
+ QPushButton, QLabel, QStyledItemDelegate
5
+
6
+ from ok.config.Config import Config
7
+ from ok.gui.Communicate import communicate
8
+
9
+ LOG_BG_TRANS = 80
10
+ color_codes = {
11
+ "INFO": QColor(85, 85, 255, LOG_BG_TRANS), # Light blue
12
+ "DEBUG": QColor(85, 255, 85, LOG_BG_TRANS), # Light green
13
+ "WARNING": QColor(255, 255, 85, LOG_BG_TRANS), # Yellow
14
+ "ERROR": QColor(255, 85, 85, LOG_BG_TRANS), # Red
15
+ }
16
+
17
+
18
+ class ColoredText:
19
+ """
20
+ Class to store colored text with its format code.
21
+ """
22
+
23
+ def __init__(self, text, format, level):
24
+ self.text = text
25
+ self.format = format
26
+ self.level = level
27
+
28
+
29
+ class ColorDelegate(QStyledItemDelegate):
30
+ def __init__(self, parent=None):
31
+ super(ColorDelegate, self).__init__(parent)
32
+
33
+ def paint(self, painter, option, index):
34
+ # Get the color from the model
35
+ color = index.data(Qt.ForegroundRole)
36
+ if color:
37
+ painter.fillRect(option.rect, color)
38
+ super(ColorDelegate, self).paint(painter, option, index)
39
+
40
+
41
+ class LogModel(QAbstractListModel):
42
+ def __init__(self, log_list):
43
+ super(LogModel, self).__init__()
44
+ self.log_list = log_list
45
+ self.logs = []
46
+ self.filtered_logs = self.logs[:]
47
+ self.current_level = "ALL"
48
+ self.current_keyword = ""
49
+
50
+ def data(self, index, role):
51
+ if role == Qt.DisplayRole:
52
+ return self.filtered_logs[index.row()].text
53
+ elif role == Qt.ForegroundRole:
54
+ return self.filtered_logs[index.row()].format
55
+
56
+ def rowCount(self, index):
57
+ return len(self.filtered_logs)
58
+
59
+ def add_log(self, level, message):
60
+ # Create colored text based on level
61
+ color_format = self.get_color_format(level)
62
+ colored_text = ColoredText(message, color_format, level)
63
+
64
+ if len(self.logs) >= 500:
65
+ self.beginRemoveRows(QModelIndex(), 0, 0)
66
+ self.logs.pop(0)
67
+ self.endRemoveRows()
68
+
69
+ self.beginInsertRows(QModelIndex(), self.rowCount(QModelIndex()), self.rowCount(QModelIndex()))
70
+ self.logs.append(colored_text)
71
+ self.endInsertRows()
72
+
73
+ self.filter_logs(self.current_level, self.current_keyword)
74
+
75
+ def filter_logs(self, level, keyword):
76
+ self.current_level = level
77
+ self.current_keyword = keyword
78
+ keyword = keyword.lower()
79
+
80
+ # Get the numeric severity for the current level
81
+ current_level_severity = level_severity.get(level, 0)
82
+
83
+ # Filter logs based on severity level and keyword
84
+ if level == "ALL":
85
+ self.filtered_logs = [log for log in self.logs if keyword in log.text.lower()]
86
+ else:
87
+ self.filtered_logs = [
88
+ log for log in self.logs
89
+ if level_severity.get(log.level, 0) >= current_level_severity
90
+ and keyword in log.text.lower()
91
+ ]
92
+
93
+ self.layoutChanged.emit()
94
+ self.log_list.scrollToBottom()
95
+
96
+ def get_color_format(self, level):
97
+ # Define color codes for different levels
98
+
99
+ return color_codes.get(level, QColor()) # Return default color for unknown levels
100
+
101
+
102
+ log_levels = {10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR"}
103
+ level_severity = {v: k for k, v in log_levels.items()}
104
+
105
+
106
+ class LogWindow(QWidget):
107
+ def __init__(self, app_config):
108
+ super().__init__()
109
+ self.setWindowTitle('Log Viewer')
110
+ self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Tool)
111
+ self.setAttribute(Qt.WA_TranslucentBackground)
112
+
113
+ self.config = Config({'width': 800, 'height': 300, 'x': 0, 'y': 0,
114
+ 'level': 'ALL'},
115
+ app_config.get('config_folder'), 'log_window')
116
+ self.setGeometry(self.config['x'], self.config['y'], self.config['width'], self.config['height'])
117
+
118
+ self.refresh_signal = Signal()
119
+
120
+ self.old_pos = None
121
+
122
+ # Layouts
123
+ self.layout = QVBoxLayout()
124
+ self.filter_layout = QHBoxLayout()
125
+
126
+ # Widgets
127
+ self.log_list = QListView()
128
+ self.log_list.setStyleSheet("background:rgba(0,0,0,60);")
129
+ self.log_list.setSelectionMode(QAbstractItemView.NoSelection)
130
+ self.log_list.setItemDelegate(ColorDelegate())
131
+
132
+ self.level_filter = QComboBox()
133
+ self.level_filter.addItems(["ALL", "DEBUG", "INFO", "WARNING", "ERROR"])
134
+ self.level_filter.setCurrentText(self.config.get('level'))
135
+ self.level_filter.currentIndexChanged.connect(self.filter_logs)
136
+
137
+ self.keyword_filter = QLineEdit()
138
+ self.keyword_filter.setPlaceholderText("Filter by keyword")
139
+ self.keyword_filter.textChanged.connect(self.filter_logs)
140
+
141
+ self.drag_button = QLabel(self.tr("Drag"))
142
+ self.drag_button.setStyleSheet('background:rgba(0,0,0,255)')
143
+
144
+ self.close_button = QPushButton(self.tr("Close"))
145
+ self.close_button.clicked.connect(self.close)
146
+
147
+ # Adding widgets to layouts
148
+ self.filter_layout.addWidget(self.level_filter)
149
+ self.filter_layout.addWidget(self.keyword_filter, stretch=1)
150
+ self.filter_layout.addWidget(self.drag_button)
151
+ self.filter_layout.addWidget(self.close_button)
152
+
153
+ self.layout.addLayout(self.filter_layout)
154
+ self.layout.addWidget(self.log_list)
155
+
156
+ self.setLayout(self.layout)
157
+
158
+ self.log_model = LogModel(self.log_list)
159
+ self.log_list.setModel(self.log_model)
160
+ communicate.log.connect(self.add_log)
161
+
162
+ self.logs = []
163
+ self.filter_logs()
164
+
165
+ def add_log(self, level_no, message):
166
+ self.logs.append(message)
167
+ self.log_model.add_log(log_levels.get(level_no, 'DEBUG'), message)
168
+
169
+ def filter_logs(self):
170
+ level = self.level_filter.currentText()
171
+ self.config['level'] = level
172
+ keyword = self.keyword_filter.text()
173
+ self.log_model.filter_logs(level, keyword)
174
+
175
+ def mousePressEvent(self, event):
176
+ if event.button() == Qt.LeftButton:
177
+ self.old_pos = event.globalPos()
178
+
179
+ def mouseMoveEvent(self, event):
180
+ if self.old_pos:
181
+ delta = QPoint(event.globalPos() - self.old_pos)
182
+ self.move(self.x() + delta.x(), self.y() + delta.y())
183
+ self.old_pos = event.globalPos()
184
+
185
+ def mouseReleaseEvent(self, event):
186
+ if event.button() == Qt.LeftButton:
187
+ self.config['x'] = self.x()
188
+ self.config['y'] = self.y()
189
+ self.old_pos = None
@@ -78,7 +78,6 @@ class Screenshot(QObject):
78
78
  self.remove_expired()
79
79
  if self.click_screenshot_folder is not None and frame is not None:
80
80
  self.add_task(frame, self.click_screenshot_folder, key)
81
- communicate.update_overlay.emit()
82
81
 
83
82
  def remove_expired(self):
84
83
  current_time = time.time()
@@ -7,7 +7,7 @@ from ok.gui.Communicate import communicate
7
7
  from ok.gui.common.OKIcon import OKIcon
8
8
  from ok.gui.tasks.ConfigItemFactory import config_widget
9
9
  from ok.task.BaseTask import BaseTask
10
- from ok.task.OneTimeTask import OneTimeTask
10
+ from ok.task.TriggerTask import TriggerTask
11
11
 
12
12
 
13
13
  class TaskCard(ExpandSettingCard):
@@ -19,7 +19,7 @@ class TaskCard(ExpandSettingCard):
19
19
  self.addWidget(self.reset_config)
20
20
  self.reset_config.clicked.connect(self.reset_clicked)
21
21
 
22
- if isinstance(task, OneTimeTask):
22
+ if not isinstance(task, TriggerTask):
23
23
  self.task_buttons = TaskButtons(self.task)
24
24
  self.addWidget(self.task_buttons)
25
25
  else:
@@ -49,10 +49,10 @@ class TaskCard(ExpandSettingCard):
49
49
 
50
50
  def update_buttons(self, task):
51
51
  if task == self.task:
52
- if isinstance(task, OneTimeTask):
53
- self.task_buttons.update_buttons()
54
- else:
52
+ if isinstance(task, TriggerTask):
55
53
  self.enable_button.setChecked(task.enabled)
54
+ else:
55
+ self.task_buttons.update_buttons()
56
56
 
57
57
  def check_changed(self, checked):
58
58
  if checked:
@@ -16,7 +16,7 @@ class BaseInteraction:
16
16
 
17
17
  def send_key_down(self, key):
18
18
  pass
19
-
19
+
20
20
  def send_key_up(self, key):
21
21
  pass
22
22
 
@@ -31,6 +31,6 @@ class BaseInteraction:
31
31
 
32
32
  def click(self, x=-1, y=-1, name=None):
33
33
  if name is None:
34
- logger.info(f"click {x, y}")
34
+ logger.debug(f"click {x, y}")
35
35
  else:
36
- logger.info(f"click {name} {x, y}")
36
+ logger.debug(f"click {name} {x, y}")
@@ -90,7 +90,7 @@ class OCR:
90
90
  self.click_box(box)
91
91
  return box
92
92
  else:
93
- logger.error(f'wait ocr no box {x} {y} {width} {height} {to_x} {to_y} {match}')
93
+ logger.warning(f'wait ocr no box {x} {y} {width} {height} {to_x} {to_y} {match}')
94
94
 
95
95
  def wait_ocr(self, x=0, y=0, to_x=1, to_y=1, width=0, height=0, name=None, box=None,
96
96
  match: str | List[str] | Pattern[str] | List[Pattern[str]] | None = None, threshold=0,
@@ -27,6 +27,34 @@ class BaseTask(ExecutorOperation):
27
27
  self._paused = False
28
28
  self.lock = threading.Lock()
29
29
  self._handler = None
30
+ self._done = False
31
+ self.running = False
32
+
33
+ def get_status(self):
34
+ if self.running:
35
+ return "Running"
36
+ elif self.enabled:
37
+ if self.paused:
38
+ return "Paused"
39
+ else:
40
+ return "In Queue"
41
+ else:
42
+ return "Not Started"
43
+
44
+ def enable(self):
45
+ if not self._enabled:
46
+ self._enabled = True
47
+ self.info_clear()
48
+ communicate.task.emit(self)
49
+ self._done = False
50
+
51
+ @property
52
+ def done(self):
53
+ return self._done
54
+
55
+ def set_done(self):
56
+ self._done = True
57
+ self.disable()
30
58
 
31
59
  @property
32
60
  def handler(self) -> Handler:
@@ -120,20 +148,11 @@ class BaseTask(ExecutorOperation):
120
148
  def validate_config(self, key, value):
121
149
  pass
122
150
 
123
- def enable(self):
124
- if not self._enabled:
125
- self._enabled = True
126
- self.info_clear()
127
- communicate.task.emit(self)
128
-
129
151
  def disable(self):
130
152
  self._enabled = False
131
153
  self.executor.current_task = None
132
154
  communicate.task.emit(self)
133
155
 
134
- def get_status(self):
135
- pass
136
-
137
156
  def run(self):
138
157
  pass
139
158