ok-script 0.0.96__tar.gz → 0.0.98__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.
- {ok-script-0.0.96 → ok-script-0.0.98}/PKG-INFO +1 -1
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/HwndWindow.py +10 -6
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/adb/ADBCaptureMethod.py +1 -18
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/adb/DeviceManager.py +82 -27
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/windows/WindowsGraphicsCaptureMethod.py +6 -4
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/color/Color.py +6 -1
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/feature/Box.py +3 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/feature/FeatureSet.py +2 -2
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/feature/FindFeature.py +16 -5
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/App.py +0 -7
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/debug/DebugTab.py +30 -2
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/debug/LogWindow.py +11 -9
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/OneTimeTaskTab.py +1 -1
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/TaskCard.py +6 -6
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/TriggerTaskTab.py +1 -1
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/interaction/Win32Interaction.py +1 -1
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/ocr/OCR.py +2 -2
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/task/ExecutorOperation.py +6 -5
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/task/TaskExecutor.py +24 -7
- {ok-script-0.0.96 → ok-script-0.0.98}/ok_script.egg-info/PKG-INFO +1 -1
- {ok-script-0.0.96 → ok-script-0.0.98}/setup.py +1 -1
- {ok-script-0.0.96 → ok-script-0.0.98}/README.md +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/OK.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/alas/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/alas/emulator_base.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/alas/emulator_windows.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/alas/platform_base.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/alas/platform_windows.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/alas/utils.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/BaseCaptureMethod.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/adb/WindowsCaptureFactory.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/adb/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/adb/bin/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/image/ImageCaptureMethod.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/image/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/windows/BaseWindowsCaptureMethod.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/windows/BitBltCaptureMethod.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/windows/DesktopDuplicationCaptureMethod.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/windows/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/windows/d3d11.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/windows/dump.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/windows/utils.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/windows/window.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/color/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/config/Config.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/config/InfoDict.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/config/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/feature/CompressCoco.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/feature/Feature.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/feature/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/firebase/Analytics.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/firebase/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/Communicate.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/MainWindow.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/MessageWindow.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/StartController.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/TabTitles.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/about/AboutTab.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/about/HttpTextEdit.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/about/VersionCard.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/about/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/common/OKIcon.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/common/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/common/config.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/common/style_sheet.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/debug/AspectRatioWidget.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/debug/FrameWidget.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/debug/InfoWidget.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/debug/Screenshot.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/debug/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/i18n/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/i18n/path.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/i18n/update.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/icon/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/icon/icon.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/overlay/OverlayWindow.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/overlay/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/qss/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/resources.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/settings/SettingTab.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/settings/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/start/SelectCaptureListView.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/start/StartCard.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/start/StartTab.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/start/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/ConfigItemFactory.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/ConfigLabelAndWidget.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/LabelAndDoubleSpinBox.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/LabelAndDropDown.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/LabelAndLineEdit.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/LabelAndList.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/LabelAndSpinBox.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/LabelAndSwitchButton.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/LabelAndWidget.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/ModifyListDialog.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/ModifyListItem.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/StartButton.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/TaskOpButton.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/TaskTab.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/TooltipTableWidget.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/util/Alert.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/util/InitWorker.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/util/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/Card.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/EmptyCard.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/FramelessDialog.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/ListTableWidgetItem.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/NumericTableWidgetItem.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/StartLoadingDialog.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/StatusBar.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/Tab.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/TabWidget.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/UpdateConfigWidgetItem.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/YesNonWidgetItem.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/interaction/ADBInteraction.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/interaction/BaseInteraction.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/interaction/DoNothingInteraction.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/interaction/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/logging/Logger.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/logging/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/ocr/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Foundation/Collections.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Foundation/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Globalization/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Graphics/Capture/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Graphics/DirectX/Direct3D11/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Graphics/DirectX/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Graphics/Imaging/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Graphics/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Media/Ocr/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Media/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Security/Cryptography/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Security/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Storage/Streams/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Storage/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/delegate.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/export.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/idldsl.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/inspectable.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/roapi.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/types.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/winstring.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/save/BlackBarProcessor.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/save/PostProcessor.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/save/SaveByInterval.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/save/SaveByKeyPress.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/save/SaveMethodBase.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/save/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/scene/FeatureScene.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/scene/Scene.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/scene/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/stats/StreamStats.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/stats/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/task/BaseTask.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/task/TriggerTask.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/task/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/update/GithubMultiDownloader.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/update/Updater.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/update/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/update/gen_md5.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/util/Handler.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/util/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/util/exit_event.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/util/json.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/util/list.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/util/path.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/util/thread.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/util/win32_process.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok/util/yaml.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok_script.egg-info/SOURCES.txt +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok_script.egg-info/dependency_links.txt +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok_script.egg-info/requires.txt +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/ok_script.egg-info/top_level.txt +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/setup.cfg +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/tests/__init__.py +0 -0
- {ok-script-0.0.96 → ok-script-0.0.98}/tests/test_updater.py +0 -0
|
@@ -243,13 +243,17 @@ def enum_child_windows(biggest, frame_aspect_ratio):
|
|
|
243
243
|
|
|
244
244
|
def get_exe_by_hwnd(hwnd):
|
|
245
245
|
# Get the process ID associated with the window
|
|
246
|
-
|
|
246
|
+
try:
|
|
247
|
+
_, pid = win32process.GetWindowThreadProcessId(hwnd)
|
|
247
248
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
249
|
+
# Get the process name and executable path
|
|
250
|
+
if pid > 0:
|
|
251
|
+
process = psutil.Process(pid)
|
|
252
|
+
return process.name(), process.exe(), process.cmdline()
|
|
253
|
+
else:
|
|
254
|
+
return None, None, None
|
|
255
|
+
except Exception as e:
|
|
256
|
+
logger.error('get_exe_by_hwnd error', e)
|
|
253
257
|
return None, None, None
|
|
254
258
|
|
|
255
259
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
# original https://github.com/Toufool/AutoSplit/blob/master/src/capture_method/WindowsGraphicsCaptureMethod.py
|
|
2
|
-
import cv2
|
|
3
2
|
import numpy as np
|
|
4
3
|
from typing_extensions import override
|
|
5
4
|
|
|
@@ -26,7 +25,7 @@ class ADBCaptureMethod(BaseCaptureMethod):
|
|
|
26
25
|
def screencap(self):
|
|
27
26
|
if self.exit_event.is_set():
|
|
28
27
|
return None
|
|
29
|
-
frame = do_screencap(self.device_manager.device)
|
|
28
|
+
frame = self.device_manager.do_screencap(self.device_manager.device)
|
|
30
29
|
if frame is not None:
|
|
31
30
|
self._connected = True
|
|
32
31
|
else:
|
|
@@ -37,19 +36,3 @@ class ADBCaptureMethod(BaseCaptureMethod):
|
|
|
37
36
|
if not self._connected and self.device_manager.device is not None:
|
|
38
37
|
self.screencap()
|
|
39
38
|
return self._connected and self.device_manager.device is not None
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def do_screencap(device) -> np.ndarray | None:
|
|
43
|
-
if device is None:
|
|
44
|
-
return None
|
|
45
|
-
try:
|
|
46
|
-
png_bytes = device.shell("screencap -p", encoding=None)
|
|
47
|
-
if png_bytes is not None and len(png_bytes) > 0:
|
|
48
|
-
image_data = np.frombuffer(png_bytes, dtype=np.uint8)
|
|
49
|
-
image = cv2.imdecode(image_data, cv2.IMREAD_COLOR)
|
|
50
|
-
if image is not None:
|
|
51
|
-
return image
|
|
52
|
-
else:
|
|
53
|
-
logger.error(f"Screencap image decode error, probably disconnected")
|
|
54
|
-
except Exception as e:
|
|
55
|
-
logger.error('screencap', e)
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
import os
|
|
2
|
+
import threading
|
|
3
|
+
|
|
4
|
+
import cv2
|
|
5
|
+
import numpy as np
|
|
6
|
+
from adbutils import AdbError
|
|
2
7
|
|
|
3
8
|
from ok.alas.platform_windows import get_emulator_exe
|
|
4
9
|
from ok.capture.HwndWindow import HwndWindow, find_hwnd
|
|
5
|
-
from ok.capture.adb.ADBCaptureMethod import ADBCaptureMethod
|
|
10
|
+
from ok.capture.adb.ADBCaptureMethod import ADBCaptureMethod
|
|
6
11
|
from ok.capture.adb.WindowsCaptureFactory import update_capture_method
|
|
7
12
|
from ok.config.Config import Config
|
|
8
13
|
from ok.gui.Communicate import communicate
|
|
@@ -19,6 +24,7 @@ class DeviceManager:
|
|
|
19
24
|
def __init__(self, app_config, exit_event=None):
|
|
20
25
|
self._device = None
|
|
21
26
|
self._adb = None
|
|
27
|
+
self._adb_lock = threading.Lock()
|
|
22
28
|
supported_resolution = app_config.get(
|
|
23
29
|
'supported_resolution', {})
|
|
24
30
|
self.supported_ratio = parse_ratio(supported_resolution.get('ratio'))
|
|
@@ -47,11 +53,39 @@ class DeviceManager:
|
|
|
47
53
|
|
|
48
54
|
@property
|
|
49
55
|
def adb(self):
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
56
|
+
with self._adb_lock:
|
|
57
|
+
if self._adb is None:
|
|
58
|
+
import adbutils
|
|
59
|
+
logger.debug(f'init adb')
|
|
60
|
+
from adbutils._utils import _get_bin_dir
|
|
61
|
+
bin_dir = _get_bin_dir()
|
|
62
|
+
exe = os.path.join(bin_dir, "adb.exe" if os.name == 'nt' else 'adb')
|
|
63
|
+
from adbutils._utils import _is_valid_exe
|
|
64
|
+
if os.path.isfile(exe) and _is_valid_exe(exe):
|
|
65
|
+
os.environ['ADBUTILS_ADB_PATH'] = exe
|
|
66
|
+
logger.info(f'set ADBUTILS_ADB_PATH {os.getenv("ADBUTILS_ADB_PATH")}')
|
|
67
|
+
else:
|
|
68
|
+
logger.error(f'set ADBUTILS_ADB_PATH failed {exe}')
|
|
69
|
+
self._adb = adbutils.AdbClient(host="127.0.0.1", socket_timeout=4)
|
|
70
|
+
try:
|
|
71
|
+
self._adb.device_list()
|
|
72
|
+
except AdbError as e:
|
|
73
|
+
self.try_kill_adb(e)
|
|
74
|
+
return self._adb
|
|
75
|
+
|
|
76
|
+
def try_kill_adb(self, e=None):
|
|
77
|
+
logger.error('try kill adb server', e)
|
|
78
|
+
import psutil
|
|
79
|
+
for proc in psutil.process_iter():
|
|
80
|
+
# Check whether the process name matches
|
|
81
|
+
if proc.name() == 'adb.exe' or proc.name() == 'adb':
|
|
82
|
+
logger.info(f'kill adb by process name {proc.cmdline()}')
|
|
83
|
+
try:
|
|
84
|
+
proc.kill()
|
|
85
|
+
except Exception as e:
|
|
86
|
+
logger.error(f'kill adb server failed', e)
|
|
87
|
+
logger.info('try kill adb end')
|
|
88
|
+
# self._adb.server_kill()
|
|
55
89
|
|
|
56
90
|
def adb_connect(self, addr, try_connect=True):
|
|
57
91
|
try:
|
|
@@ -67,11 +101,12 @@ class DeviceManager:
|
|
|
67
101
|
logger.debug(f'adb_connect already connected {addr}')
|
|
68
102
|
return device
|
|
69
103
|
if try_connect:
|
|
70
|
-
self.adb.connect(addr, timeout=
|
|
104
|
+
self.adb.connect(addr, timeout=5)
|
|
71
105
|
logger.debug(f'adb_connect {addr}')
|
|
72
106
|
return self.adb_connect(addr, try_connect=False)
|
|
73
|
-
except
|
|
74
|
-
logger.error(f"adb connect error
|
|
107
|
+
except AdbError as e:
|
|
108
|
+
logger.error(f"adb connect error {addr}", e)
|
|
109
|
+
self.try_kill_adb(e)
|
|
75
110
|
except Exception as e:
|
|
76
111
|
logger.error(f"adb connect error return none {addr}", e)
|
|
77
112
|
|
|
@@ -137,11 +172,12 @@ class DeviceManager:
|
|
|
137
172
|
from ok.alas.emulator_windows import EmulatorManager
|
|
138
173
|
manager = EmulatorManager()
|
|
139
174
|
installed_emulators = manager.all_emulator_instances
|
|
175
|
+
logger.info(f'installed emulators {installed_emulators}')
|
|
140
176
|
for emulator in installed_emulators:
|
|
141
177
|
preferred = self.get_preferred_device()
|
|
142
178
|
if current and preferred is not None and preferred['imei'] != emulator.name:
|
|
143
179
|
logger.debug(f"refresh current only skip others {preferred['imei']} != {emulator.name}")
|
|
144
|
-
|
|
180
|
+
continue
|
|
145
181
|
adb_device = self.adb_connect(emulator.serial)
|
|
146
182
|
width, height = self.get_resolution(adb_device) if adb_device is not None else 0, 0
|
|
147
183
|
name, hwnd, full_path, x, y, width, height = find_hwnd(None,
|
|
@@ -164,7 +200,7 @@ class DeviceManager:
|
|
|
164
200
|
if device is not None:
|
|
165
201
|
if resolution := self.resolution_dict.get(device.serial):
|
|
166
202
|
return resolution
|
|
167
|
-
frame = do_screencap(device)
|
|
203
|
+
frame = self.do_screencap(device)
|
|
168
204
|
if frame is not None:
|
|
169
205
|
height, width, _ = frame.shape
|
|
170
206
|
if self.supported_ratio is None or abs(width / height - self.supported_ratio) < 0.01:
|
|
@@ -198,15 +234,43 @@ class DeviceManager:
|
|
|
198
234
|
self.start()
|
|
199
235
|
logger.debug(f'preferred device: {preferred}')
|
|
200
236
|
|
|
201
|
-
|
|
202
|
-
|
|
237
|
+
def shell_device(self, device, *args, **kwargs):
|
|
238
|
+
kwargs.setdefault('timeout', 5)
|
|
203
239
|
try:
|
|
204
|
-
return device.shell(
|
|
205
|
-
|
|
240
|
+
return device.shell(*args, **kwargs)
|
|
241
|
+
except AdbError as e:
|
|
242
|
+
logger.error(f"adb shell AdbError try kill server {device}", e)
|
|
243
|
+
self.try_kill_adb(e)
|
|
244
|
+
addr = self.get_preferred_device()['address']
|
|
245
|
+
self.refresh_emulators()
|
|
246
|
+
self.refresh_phones()
|
|
247
|
+
new_addr = self.get_preferred_device()['address']
|
|
248
|
+
logger.error(f"shell_wrapper error occurred, try refresh_emulators {addr} {new_addr}", e)
|
|
249
|
+
device = self.adb_connect(device.serial)
|
|
250
|
+
return device.shell(*args, **kwargs)
|
|
206
251
|
except Exception as e:
|
|
207
|
-
logger.error(f"
|
|
252
|
+
logger.error(f"adb shell error maybe offline {device}", e)
|
|
208
253
|
return None
|
|
209
254
|
|
|
255
|
+
def adb_get_imei(self, device):
|
|
256
|
+
return (self.shell_device(device, "settings get secure android_id") or
|
|
257
|
+
self.shell_device(device, "service call iphonesubinfo 4") or device.prop.model)
|
|
258
|
+
|
|
259
|
+
def do_screencap(self, device) -> np.ndarray | None:
|
|
260
|
+
if device is None:
|
|
261
|
+
return None
|
|
262
|
+
try:
|
|
263
|
+
png_bytes = self.shell_device(device, "screencap -p", encoding=None)
|
|
264
|
+
if png_bytes is not None and len(png_bytes) > 0:
|
|
265
|
+
image_data = np.frombuffer(png_bytes, dtype=np.uint8)
|
|
266
|
+
image = cv2.imdecode(image_data, cv2.IMREAD_COLOR)
|
|
267
|
+
if image is not None:
|
|
268
|
+
return image
|
|
269
|
+
else:
|
|
270
|
+
logger.error(f"Screencap image decode error, probably disconnected")
|
|
271
|
+
except Exception as e:
|
|
272
|
+
logger.error('screencap', e)
|
|
273
|
+
|
|
210
274
|
def get_preferred_device(self):
|
|
211
275
|
imei = self.config.get("preferred")
|
|
212
276
|
preferred = self.device_dict.get(imei)
|
|
@@ -331,19 +395,10 @@ class DeviceManager:
|
|
|
331
395
|
|
|
332
396
|
def shell(self, *args, **kwargs):
|
|
333
397
|
# Set default timeout to 5 if not provided
|
|
334
|
-
kwargs.setdefault('timeout', 5)
|
|
335
398
|
|
|
336
399
|
device = self.device
|
|
337
400
|
if device is not None:
|
|
338
|
-
|
|
339
|
-
return device.shell(*args, **kwargs)
|
|
340
|
-
except AdbError as e:
|
|
341
|
-
logger.debug(f'shell adb error {args} {e}')
|
|
342
|
-
except Exception as e:
|
|
343
|
-
addr = self.get_preferred_device()['address']
|
|
344
|
-
self.refresh_emulators()
|
|
345
|
-
new_addr = self.get_preferred_device()['address']
|
|
346
|
-
logger.error(f"shell_wrapper error occurred, try refresh_emulators {addr} {new_addr}", e)
|
|
401
|
+
return self.shell_device(device, *args, **kwargs)
|
|
347
402
|
else:
|
|
348
403
|
raise Exception('Device is none')
|
|
349
404
|
|
|
@@ -51,11 +51,12 @@ class WindowsGraphicsCaptureMethod(BaseWindowsCaptureMethod):
|
|
|
51
51
|
|
|
52
52
|
def convert_dx_frame(self):
|
|
53
53
|
frame = self.last_dx_frame
|
|
54
|
-
self.last_dx_frame = None
|
|
55
54
|
if not frame:
|
|
56
|
-
logger.warning('convert_dx_frame self.last_dx_frame is none')
|
|
55
|
+
# logger.warning('convert_dx_frame self.last_dx_frame is none')
|
|
57
56
|
return None
|
|
58
|
-
|
|
57
|
+
start = time.time()
|
|
58
|
+
dx_time = self.last_frame_time
|
|
59
|
+
self.last_dx_frame = None
|
|
59
60
|
need_reset_framepool = False
|
|
60
61
|
if frame.ContentSize.Width != self.last_size.Width or frame.ContentSize.Height != self.last_size.Height:
|
|
61
62
|
need_reset_framepool = True
|
|
@@ -94,6 +95,7 @@ class WindowsGraphicsCaptureMethod(BaseWindowsCaptureMethod):
|
|
|
94
95
|
(desc.Height, mapinfo.RowPitch // 4, 4))[
|
|
95
96
|
:, :desc.Width].copy()
|
|
96
97
|
self.immediatedc.Unmap(cputex, 0)
|
|
98
|
+
# logger.debug(f'frame latency {(time.time() - start):.3f} {(time.time() - dx_time):.3f}')
|
|
97
99
|
return img
|
|
98
100
|
except OSError as e:
|
|
99
101
|
if e.winerror == d3d11.DXGI_ERROR_DEVICE_REMOVED or e.winerror == d3d11.DXGI_ERROR_DEVICE_RESET:
|
|
@@ -150,7 +152,7 @@ class WindowsGraphicsCaptureMethod(BaseWindowsCaptureMethod):
|
|
|
150
152
|
self.evtoken = item.add_Closed(delegate)
|
|
151
153
|
self.frame_pool = Direct3D11CaptureFramePool.CreateFreeThreaded(self.rtdevice,
|
|
152
154
|
DirectXPixelFormat.B8G8R8A8UIntNormalized,
|
|
153
|
-
|
|
155
|
+
1, item.Size)
|
|
154
156
|
self.session = self.frame_pool.CreateCaptureSession(item)
|
|
155
157
|
pool = self.frame_pool
|
|
156
158
|
pool.add_FrameArrived(
|
|
@@ -104,6 +104,11 @@ def find_color_rectangles(image, color_range, min_width, min_height, max_width=-
|
|
|
104
104
|
raise ValueError("Image not found or path is incorrect")
|
|
105
105
|
if box is not None:
|
|
106
106
|
image = image[box.y:box.y + box.height, box.x:box.x + box.width, :3]
|
|
107
|
+
x_offset = box.x
|
|
108
|
+
y_offset = box.y
|
|
109
|
+
else:
|
|
110
|
+
x_offset = 0
|
|
111
|
+
y_offset = 0
|
|
107
112
|
|
|
108
113
|
# Convert color range to BGR format for OpenCV
|
|
109
114
|
lower_bound = np.array([color_range['b'][0], color_range['g'][0], color_range['r'][0]], dtype="uint8")
|
|
@@ -139,7 +144,7 @@ def find_color_rectangles(image, color_range, min_width, min_height, max_width=-
|
|
|
139
144
|
if percent >= threshold:
|
|
140
145
|
# Store the result
|
|
141
146
|
results.append(
|
|
142
|
-
Box(x, y, w, h, confidence=percent)
|
|
147
|
+
Box(x + x_offset, y + y_offset, w, h, confidence=percent)
|
|
143
148
|
)
|
|
144
149
|
|
|
145
150
|
return results
|
|
@@ -95,6 +95,9 @@ class Box:
|
|
|
95
95
|
return Box(self.x + x_offset, self.y + y_offset, self.width + width_offset, self.height + height_offset,
|
|
96
96
|
self.confidence, name or self.name)
|
|
97
97
|
|
|
98
|
+
def crop_frame(self, frame):
|
|
99
|
+
return frame[self.y:self.y + self.height, self.x:self.x + self.width]
|
|
100
|
+
|
|
98
101
|
def center(self):
|
|
99
102
|
return self.x + self.width / 2, self.y + self.height / 2
|
|
100
103
|
|
|
@@ -174,7 +174,7 @@ class FeatureSet:
|
|
|
174
174
|
template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
|
|
175
175
|
if category_name.startswith('edge_'):
|
|
176
176
|
search_area = cv2.cvtColor(search_area, cv2.COLOR_BGR2GRAY)
|
|
177
|
-
|
|
177
|
+
search_area = cv2.Canny(search_area, self.canny_lower, self.canny_higher)
|
|
178
178
|
elif category_name.startswith('gray_'):
|
|
179
179
|
search_area = cv2.cvtColor(search_area, cv2.COLOR_BGR2GRAY)
|
|
180
180
|
|
|
@@ -258,7 +258,7 @@ def read_from_json(coco_json, width=-1, height=-1, canny_lower=50, canny_upper=1
|
|
|
258
258
|
if ok_compressed:
|
|
259
259
|
if category_name.startswith('edge_'):
|
|
260
260
|
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
|
261
|
-
|
|
261
|
+
image = cv2.Canny(image, canny_lower, canny_upper)
|
|
262
262
|
elif category_name.startswith('gray_'):
|
|
263
263
|
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
|
264
264
|
feature_dict[category_name] = Feature(image, x, y)
|
|
@@ -31,13 +31,24 @@ class FindFeature:
|
|
|
31
31
|
setattr(self, feature, result)
|
|
32
32
|
return ret
|
|
33
33
|
|
|
34
|
+
def wait_feature(self, feature, horizontal_variance=0, vertical_variance=0, threshold=0, wait_until_before_delay=-1,
|
|
35
|
+
time_out=0, pre_action=None, post_action=None, use_gray_scale=False, box=None,
|
|
36
|
+
raise_if_not_found=False):
|
|
37
|
+
return self.wait_until(
|
|
38
|
+
lambda: self.find_one(feature, horizontal_variance, vertical_variance, threshold,
|
|
39
|
+
use_gray_scale=use_gray_scale, box=box),
|
|
40
|
+
time_out,
|
|
41
|
+
pre_action,
|
|
42
|
+
post_action, wait_until_before_delay, raise_if_not_found)
|
|
43
|
+
|
|
34
44
|
def wait_click_feature(self, feature, horizontal_variance=0, vertical_variance=0, threshold=0, relative_x=0.5,
|
|
35
45
|
relative_y=0.5,
|
|
36
|
-
time_out=0, pre_action=None, post_action=None):
|
|
37
|
-
box = self.wait_until(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
time_out=0, pre_action=None, post_action=None, box=None, raise_if_not_found=True):
|
|
47
|
+
box = self.wait_until(
|
|
48
|
+
lambda: self.find_one(feature, horizontal_variance, vertical_variance, threshold, box=box),
|
|
49
|
+
time_out,
|
|
50
|
+
pre_action,
|
|
51
|
+
post_action, raise_if_not_found)
|
|
41
52
|
if box is not None:
|
|
42
53
|
self.click_box(box, relative_x, relative_y)
|
|
43
54
|
return True
|
|
@@ -47,7 +47,6 @@ class App:
|
|
|
47
47
|
self.loading_window = None
|
|
48
48
|
self.overlay_window = None
|
|
49
49
|
self.main_window = None
|
|
50
|
-
self.log_window = None
|
|
51
50
|
self.exit_event = exit_event
|
|
52
51
|
self.icon = QIcon(self.config.get('gui_icon') or ":/icon/icon.ico")
|
|
53
52
|
if self.config.get('analytics'):
|
|
@@ -98,12 +97,6 @@ class App:
|
|
|
98
97
|
if self.overlay and ok.gui.device_manager.hwnd is not None:
|
|
99
98
|
self.overlay_window = OverlayWindow(ok.gui.device_manager.hwnd)
|
|
100
99
|
|
|
101
|
-
if self.config.get('debug'):
|
|
102
|
-
from ok.gui.debug.LogWindow import LogWindow
|
|
103
|
-
self.log_window = LogWindow(self.config)
|
|
104
|
-
self.log_window.show()
|
|
105
|
-
logger.debug('showing log_window')
|
|
106
|
-
|
|
107
100
|
self.main_window = MainWindow(self.config, self.icon, self.title, self.version, self.overlay, self.about,
|
|
108
101
|
self.exit_event)
|
|
109
102
|
# Set the window title here
|
|
@@ -29,6 +29,9 @@ class DebugTab(Tab):
|
|
|
29
29
|
|
|
30
30
|
self.config = Config({'target_task': "", 'target_images': [], 'target_function': ""},
|
|
31
31
|
app_config.get('config_folder'), 'debug')
|
|
32
|
+
self.log_window_config = Config({'width': 800, 'height': 300, 'x': 0, 'y': 0, 'keyword': '',
|
|
33
|
+
'level': 'ALL', 'show': True},
|
|
34
|
+
app_config.get('config_folder'), 'log_window')
|
|
32
35
|
tool_widget = QWidget()
|
|
33
36
|
layout = FlowLayout(tool_widget, False)
|
|
34
37
|
|
|
@@ -53,7 +56,14 @@ class DebugTab(Tab):
|
|
|
53
56
|
ocr_button.clicked.connect(lambda: self.handler.post(self.ocr))
|
|
54
57
|
layout.addWidget(ocr_button)
|
|
55
58
|
|
|
56
|
-
|
|
59
|
+
self.log_window = None
|
|
60
|
+
|
|
61
|
+
log_window_button = PushButton(self.tr("Open Logs"))
|
|
62
|
+
log_window_button.clicked.connect(self.toggle_log_window)
|
|
63
|
+
layout.addWidget(log_window_button)
|
|
64
|
+
|
|
65
|
+
if self.log_window_config.get('show'):
|
|
66
|
+
self.toggle_log_window()
|
|
57
67
|
|
|
58
68
|
call_task_widget = QWidget()
|
|
59
69
|
call_task_container = QVBoxLayout(call_task_widget)
|
|
@@ -98,6 +108,22 @@ class DebugTab(Tab):
|
|
|
98
108
|
self.handler.post(self.bind_hot_keys)
|
|
99
109
|
self.handler.post(self.check_hotkey, 0.1)
|
|
100
110
|
|
|
111
|
+
ok.gui.app.app.aboutToQuit.connect(self.unregister)
|
|
112
|
+
|
|
113
|
+
def toggle_log_window(self):
|
|
114
|
+
if self.log_window is None:
|
|
115
|
+
from ok.gui.debug.LogWindow import LogWindow
|
|
116
|
+
self.log_window = LogWindow(self.log_window_config)
|
|
117
|
+
self.log_window.show()
|
|
118
|
+
self.log_window_config['show'] = True
|
|
119
|
+
elif self.log_window.isVisible():
|
|
120
|
+
self.log_window.hide()
|
|
121
|
+
self.log_window_config['show'] = False
|
|
122
|
+
else:
|
|
123
|
+
self.log_window_config['show'] = True
|
|
124
|
+
self.log_window.show()
|
|
125
|
+
logger.debug('showing log_window')
|
|
126
|
+
|
|
101
127
|
def check_hotkey(self):
|
|
102
128
|
# Example event type, you should use the appropriate QEvent.Type for your case
|
|
103
129
|
msg = wintypes.MSG()
|
|
@@ -127,8 +153,10 @@ class DebugTab(Tab):
|
|
|
127
153
|
logger.debug("Failed to register hotkey for Alt+Ctrl+S")
|
|
128
154
|
logger.debug('bind_hot_keys')
|
|
129
155
|
|
|
130
|
-
|
|
156
|
+
@staticmethod
|
|
157
|
+
def unregister():
|
|
131
158
|
# Unregister the hotkeys
|
|
159
|
+
logger.debug('Unregister the hotkeys')
|
|
132
160
|
windll.user32.UnregisterHotKey(None, 1)
|
|
133
161
|
windll.user32.UnregisterHotKey(None, 2)
|
|
134
162
|
|
|
@@ -4,7 +4,6 @@ from PySide6.QtWidgets import QWidget, \
|
|
|
4
4
|
QStyledItemDelegate, QListView, QVBoxLayout, QHBoxLayout, QAbstractItemView, QComboBox, QLineEdit, QLabel, \
|
|
5
5
|
QPushButton
|
|
6
6
|
|
|
7
|
-
from ok.config.Config import Config
|
|
8
7
|
from ok.gui.Communicate import communicate
|
|
9
8
|
|
|
10
9
|
LOG_BG_TRANS = 80
|
|
@@ -70,9 +69,6 @@ class LogModel(QAbstractListModel):
|
|
|
70
69
|
self.do_filter_logs()
|
|
71
70
|
self.endInsertRows()
|
|
72
71
|
|
|
73
|
-
# self.layoutChanged.emit()
|
|
74
|
-
# self.log_list.scrollToBottom()
|
|
75
|
-
|
|
76
72
|
def do_filter_logs(self):
|
|
77
73
|
|
|
78
74
|
keyword = self.current_keyword.lower()
|
|
@@ -109,15 +105,13 @@ level_severity = {v: k for k, v in log_levels.items()}
|
|
|
109
105
|
|
|
110
106
|
|
|
111
107
|
class LogWindow(QWidget):
|
|
112
|
-
def __init__(self,
|
|
108
|
+
def __init__(self, config):
|
|
113
109
|
super().__init__()
|
|
114
110
|
self.setWindowTitle('Log Viewer')
|
|
115
111
|
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Tool)
|
|
116
112
|
self.setAttribute(Qt.WA_TranslucentBackground)
|
|
117
113
|
|
|
118
|
-
self.config =
|
|
119
|
-
'level': 'ALL'},
|
|
120
|
-
app_config.get('config_folder'), 'log_window')
|
|
114
|
+
self.config = config
|
|
121
115
|
self.setGeometry(self.config['x'], self.config['y'], self.config['width'], self.config['height'])
|
|
122
116
|
|
|
123
117
|
self.old_pos = None
|
|
@@ -139,6 +133,8 @@ class LogWindow(QWidget):
|
|
|
139
133
|
|
|
140
134
|
self.keyword_filter = QLineEdit()
|
|
141
135
|
self.keyword_filter.setPlaceholderText("Filter by keyword")
|
|
136
|
+
if keyword := self.config.get('keyword'):
|
|
137
|
+
self.keyword_filter.setText(keyword)
|
|
142
138
|
self.keyword_filter.textChanged.connect(self.filter_logs)
|
|
143
139
|
|
|
144
140
|
self.drag_button = QLabel(self.tr("Drag"))
|
|
@@ -162,6 +158,11 @@ class LogWindow(QWidget):
|
|
|
162
158
|
self.log_list.setModel(self.log_model)
|
|
163
159
|
|
|
164
160
|
communicate.log.connect(self.add_log)
|
|
161
|
+
self.filter_logs()
|
|
162
|
+
|
|
163
|
+
def close(self):
|
|
164
|
+
super().close()
|
|
165
|
+
self.config['show'] = False
|
|
165
166
|
|
|
166
167
|
def add_log(self, level_no, message):
|
|
167
168
|
# print('add_log', level_no, message)
|
|
@@ -170,8 +171,9 @@ class LogWindow(QWidget):
|
|
|
170
171
|
|
|
171
172
|
def filter_logs(self):
|
|
172
173
|
level = self.level_filter.currentText()
|
|
173
|
-
self.config['level'] = level
|
|
174
174
|
keyword = self.keyword_filter.text()
|
|
175
|
+
self.config['keyword'] = keyword
|
|
176
|
+
self.config['level'] = level
|
|
175
177
|
self.log_model.filter_logs(level, keyword)
|
|
176
178
|
|
|
177
179
|
def mousePressEvent(self, event):
|
|
@@ -7,19 +7,19 @@ 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.TriggerTask import TriggerTask
|
|
11
10
|
|
|
12
11
|
|
|
13
12
|
class TaskCard(ExpandSettingCard):
|
|
14
|
-
def __init__(self, task: BaseTask):
|
|
13
|
+
def __init__(self, task: BaseTask, onetime):
|
|
15
14
|
super().__init__(FluentIcon.INFO, task.name, task.description)
|
|
16
15
|
self.task = task
|
|
16
|
+
self.onetime = onetime
|
|
17
17
|
if task.default_config:
|
|
18
18
|
self.reset_config = PushButton(FluentIcon.CANCEL, self.tr("Reset Config"), self)
|
|
19
19
|
self.addWidget(self.reset_config)
|
|
20
20
|
self.reset_config.clicked.connect(self.reset_clicked)
|
|
21
21
|
|
|
22
|
-
if
|
|
22
|
+
if onetime:
|
|
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
|
|
53
|
-
self.enable_button.setChecked(task.enabled)
|
|
54
|
-
else:
|
|
52
|
+
if self.onetime:
|
|
55
53
|
self.task_buttons.update_buttons()
|
|
54
|
+
else:
|
|
55
|
+
self.enable_button.setChecked(task.enabled)
|
|
56
56
|
|
|
57
57
|
def check_changed(self, checked):
|
|
58
58
|
if checked:
|
|
@@ -20,7 +20,7 @@ class Win32Interaction(BaseInteraction):
|
|
|
20
20
|
if not is_admin():
|
|
21
21
|
logger.error(f"You must be an admin to use Win32Interaction")
|
|
22
22
|
|
|
23
|
-
def send_key(self, key, down_time=0.
|
|
23
|
+
def send_key(self, key, down_time=0.01):
|
|
24
24
|
if not self.capture.clickable():
|
|
25
25
|
logger.error(f"can't click on {key}, because capture is not clickable")
|
|
26
26
|
return
|
|
@@ -12,7 +12,7 @@ logger = get_logger(__name__)
|
|
|
12
12
|
|
|
13
13
|
class OCR:
|
|
14
14
|
executor = None
|
|
15
|
-
ocr_default_threshold = 0.
|
|
15
|
+
ocr_default_threshold = 0.8
|
|
16
16
|
ocr_target_height = 0
|
|
17
17
|
|
|
18
18
|
def ocr(self, x=0, y=0, to_x=1, to_y=1, match: str | List[str] | Pattern[str] | List[Pattern[str]] | None = None,
|
|
@@ -75,7 +75,7 @@ class OCR:
|
|
|
75
75
|
communicate.emit_draw_box("ocr", detected_boxes, "red")
|
|
76
76
|
communicate.emit_draw_box("ocr_zone", box, "blue")
|
|
77
77
|
logger.debug(
|
|
78
|
-
f"ocr_zone {box} found result: {
|
|
78
|
+
f"ocr_zone {box} found result: {detected_boxes}) time: {(time.time() - start):.2f} scale_factor: {scale_factor:.2f}")
|
|
79
79
|
if not detected_boxes and ocr_boxes:
|
|
80
80
|
logger.info(f'ocr detected but no match: {match} {ocr_boxes}')
|
|
81
81
|
return sort_boxes(detected_boxes)
|
|
@@ -138,7 +138,7 @@ class ExecutorOperation:
|
|
|
138
138
|
def move_relative(self, x, y):
|
|
139
139
|
self.executor.interaction.move_relative(x, y)
|
|
140
140
|
|
|
141
|
-
def click_box(self, box: Box | List[Box] = None, relative_x=0.5, relative_y=0.5, raise_if_not_found=
|
|
141
|
+
def click_box(self, box: Box | List[Box] = None, relative_x=0.5, relative_y=0.5, raise_if_not_found=False,
|
|
142
142
|
move_back=False):
|
|
143
143
|
if isinstance(box, list):
|
|
144
144
|
if len(box) > 0:
|
|
@@ -156,7 +156,6 @@ class ExecutorOperation:
|
|
|
156
156
|
return self.executor.wait_scene(scene_type, time_out, pre_action, post_action)
|
|
157
157
|
|
|
158
158
|
def sleep(self, timeout):
|
|
159
|
-
self.executor.reset_scene()
|
|
160
159
|
self.executor.sleep(timeout)
|
|
161
160
|
|
|
162
161
|
def send_key(self, key, down_time=0.02):
|
|
@@ -174,10 +173,12 @@ class ExecutorOperation:
|
|
|
174
173
|
self.executor.reset_scene()
|
|
175
174
|
self.executor.interaction.send_key_up(key)
|
|
176
175
|
|
|
177
|
-
def wait_until(self, condition, time_out=0, pre_action=None, post_action=None, wait_until_before_delay
|
|
178
|
-
|
|
176
|
+
def wait_until(self, condition, time_out=0, pre_action=None, post_action=None, wait_until_before_delay=-1,
|
|
177
|
+
raise_if_not_found=False):
|
|
178
|
+
return self.executor.wait_condition(condition, time_out, pre_action, post_action, wait_until_before_delay,
|
|
179
|
+
raise_if_not_found)
|
|
179
180
|
|
|
180
|
-
def wait_click_box(self, condition, time_out=0, pre_action=None, post_action=None, raise_if_not_found=
|
|
181
|
+
def wait_click_box(self, condition, time_out=0, pre_action=None, post_action=None, raise_if_not_found=False):
|
|
181
182
|
target = self.wait_until(condition, time_out, pre_action, post_action)
|
|
182
183
|
self.click_box(box=target, raise_if_not_found=raise_if_not_found)
|
|
183
184
|
return target
|