ok-script 0.0.58__tar.gz → 0.0.60__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.58 → ok-script-0.0.60}/PKG-INFO +1 -1
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/OK.py +2 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/capture/BaseCaptureMethod.py +3 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/capture/HwndWindow.py +1 -1
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/capture/adb/DeviceManager.py +13 -12
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/capture/adb/vbox.py +19 -19
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/capture/windows/BaseWindowsCaptureMethod.py +8 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/capture/windows/dump.py +5 -1
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/App.py +3 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/Communicate.py +1 -1
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/MainWindow.py +10 -5
- ok-script-0.0.60/ok/gui/about/AboutTab.py +145 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/about/VersionCard.py +40 -4
- ok-script-0.0.60/ok/gui/debug/DebugTab.py +53 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/debug/Screenshot.py +28 -22
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/resources.py +515 -475
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/widget/Tab.py +7 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/task/BaseTask.py +1 -1
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/update/GithubMultiDownloader.py +3 -2
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/update/Updater.py +41 -48
- ok-script-0.0.60/ok/util/Handler.py +94 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/util/exit_event.py +7 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/util/path.py +8 -3
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/util/win32_process.py +31 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok_script.egg-info/PKG-INFO +1 -1
- {ok-script-0.0.58 → ok-script-0.0.60}/ok_script.egg-info/SOURCES.txt +1 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/setup.py +1 -1
- ok-script-0.0.58/ok/gui/about/AboutTab.py +0 -160
- ok-script-0.0.58/ok/gui/debug/DebugTab.py +0 -17
- {ok-script-0.0.58 → ok-script-0.0.60}/README.md +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/capture/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/capture/adb/ADBCaptureMethod.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/capture/adb/WindowsCaptureFactory.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/capture/adb/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/capture/adb/bin/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/capture/adb/targets.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/capture/windows/BitBltCaptureMethod.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/capture/windows/DesktopDuplicationCaptureMethod.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/capture/windows/WindowsGraphicsCaptureMethod.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/capture/windows/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/capture/windows/d3d11.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/capture/windows/utils.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/capture/windows/window.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/color/Color.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/color/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/config/Config.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/config/InfoDict.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/config/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/feature/Box.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/feature/Feature.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/feature/FeatureSet.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/feature/FindFeature.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/feature/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/MessageWindow.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/TabTitles.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/about/HttpTextEdit.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/about/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/common/OKIcon.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/common/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/common/config.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/common/style_sheet.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/debug/AspectRatioWidget.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/debug/FrameWidget.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/debug/InfoWidget.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/debug/LoggerWidget.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/debug/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/i18n/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/i18n/path.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/i18n/update.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/icon/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/icon/icon.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/overlay/OverlayWindow.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/overlay/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/qss/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/settings/SettingTab.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/settings/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/start/SelectCaptureListView.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/start/SelectHwndWindow.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/start/StartCard.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/start/StartTab.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/start/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/tasks/ConfigItemFactory.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/tasks/ConfigLabelAndWidget.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/tasks/LabelAndDoubleSpinBox.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/tasks/LabelAndDropDown.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/tasks/LabelAndLineEdit.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/tasks/LabelAndList.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/tasks/LabelAndSpinBox.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/tasks/LabelAndSwitchButton.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/tasks/LabelAndWidget.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/tasks/ModifyListDialog.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/tasks/ModifyListItem.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/tasks/OneTimeTaskTab.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/tasks/StartButton.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/tasks/TaskCard.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/tasks/TaskOpButton.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/tasks/TooltipTableWidget.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/tasks/TriggerTaskTab.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/tasks/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/util/Alert.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/util/InitWorker.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/util/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/widget/Card.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/widget/EmptyCard.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/widget/FramelessDialog.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/widget/ListTableWidgetItem.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/widget/NumericTableWidgetItem.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/widget/StatusBar.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/widget/TabWidget.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/widget/UpdateConfigWidgetItem.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/widget/YesNonWidgetItem.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/gui/widget/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/interaction/ADBInteraction.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/interaction/BaseInteraction.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/interaction/Win32Interaction.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/interaction/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/logging/Logger.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/logging/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/ocr/OCR.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/ocr/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/Windows/Foundation/Collections.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/Windows/Foundation/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/Windows/Globalization/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/Windows/Graphics/Capture/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/Windows/Graphics/DirectX/Direct3D11/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/Windows/Graphics/DirectX/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/Windows/Graphics/Imaging/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/Windows/Graphics/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/Windows/Media/Ocr/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/Windows/Media/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/Windows/Security/Cryptography/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/Windows/Security/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/Windows/Storage/Streams/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/Windows/Storage/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/Windows/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/delegate.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/export.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/idldsl.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/inspectable.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/roapi.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/types.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/rotypes/winstring.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/save/BlackBarProcessor.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/save/PostProcessor.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/save/SaveByInterval.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/save/SaveByKeyPress.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/save/SaveMethodBase.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/save/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/scene/FeatureScene.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/scene/Scene.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/scene/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/stats/StreamStats.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/stats/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/task/ExecutorOperation.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/task/OneTimeTask.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/task/TaskExecutor.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/task/TriggerTask.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/task/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/update/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/update/gen_md5.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/util/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/util/json.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/util/list.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/util/thread.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok/util/yaml.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok_script.egg-info/dependency_links.txt +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok_script.egg-info/requires.txt +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/ok_script.egg-info/top_level.txt +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/setup.cfg +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/tests/__init__.py +0 -0
- {ok-script-0.0.58 → ok-script-0.0.60}/tests/test_updater.py +0 -0
|
@@ -9,7 +9,9 @@ import ok
|
|
|
9
9
|
from ok.logging.Logger import get_logger, config_logger
|
|
10
10
|
from ok.util.exit_event import ExitEvent
|
|
11
11
|
from ok.util.path import install_path_isascii
|
|
12
|
+
from ok.util.win32_process import check_mutex
|
|
12
13
|
|
|
14
|
+
check_mutex()
|
|
13
15
|
logger = get_logger(__name__)
|
|
14
16
|
|
|
15
17
|
|
|
@@ -136,7 +136,7 @@ class HwndWindow:
|
|
|
136
136
|
return ""
|
|
137
137
|
|
|
138
138
|
def __str__(self) -> str:
|
|
139
|
-
return f"title:{self.title}
|
|
139
|
+
return f"title:{self.title}_{self.exe_name}_{self.width}x{self.height}_{self.exists}_{self.visible}"
|
|
140
140
|
|
|
141
141
|
|
|
142
142
|
def find_hwnd_by_title_and_exe(title, exe_name):
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import threading
|
|
2
|
-
|
|
3
1
|
import win32gui
|
|
4
2
|
|
|
5
3
|
from ok.capture.HwndWindow import HwndWindow, find_hwnd_by_title_and_exe
|
|
@@ -11,6 +9,7 @@ from ok.gui.Communicate import communicate
|
|
|
11
9
|
from ok.interaction.ADBInteraction import ADBBaseInteraction
|
|
12
10
|
from ok.interaction.Win32Interaction import Win32Interaction
|
|
13
11
|
from ok.logging.Logger import get_logger
|
|
12
|
+
from ok.util.Handler import Handler
|
|
14
13
|
|
|
15
14
|
logger = get_logger(__name__)
|
|
16
15
|
|
|
@@ -32,14 +31,13 @@ class DeviceManager:
|
|
|
32
31
|
windows_capture_config.get('exe'))
|
|
33
32
|
self.config = Config({"devices": {}, "preferred": "none", "pc_full_path": None}, config_folder,
|
|
34
33
|
"DeviceManager")
|
|
35
|
-
self.thread = None
|
|
36
34
|
self.capture_method = None
|
|
37
|
-
self.
|
|
35
|
+
self.handler = Handler(exit_event, 'RefreshAdb')
|
|
36
|
+
self.handler.post(self.do_refresh, 5)
|
|
38
37
|
|
|
39
38
|
def refresh(self):
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
self.thread.start()
|
|
39
|
+
logger.debug('calling refresh')
|
|
40
|
+
self.handler.post(self.do_refresh, remove_existing=True)
|
|
43
41
|
|
|
44
42
|
@property
|
|
45
43
|
def device_dict(self):
|
|
@@ -61,14 +59,17 @@ class DeviceManager:
|
|
|
61
59
|
logger.debug(f'connect adb')
|
|
62
60
|
return self._adb
|
|
63
61
|
|
|
62
|
+
def adb_connect(self, addr):
|
|
63
|
+
try:
|
|
64
|
+
self.adb.connect(addr, timeout=2)
|
|
65
|
+
except Exception as e:
|
|
66
|
+
logger.error("adb connect error", e)
|
|
67
|
+
|
|
64
68
|
def connect_all(self):
|
|
65
69
|
if not self._connect_all:
|
|
66
70
|
for device in self.device_dict.values():
|
|
67
71
|
if device["device"] == "adb":
|
|
68
|
-
|
|
69
|
-
self.adb.connect(device['address'])
|
|
70
|
-
except Exception as e:
|
|
71
|
-
logger.error("adb connect error", e)
|
|
72
|
+
self.adb_connect(device['address'])
|
|
72
73
|
self._connect_all = True
|
|
73
74
|
logger.debug(f'connect_all')
|
|
74
75
|
|
|
@@ -124,7 +125,7 @@ class DeviceManager:
|
|
|
124
125
|
logger.debug(f'adb.list() {device}')
|
|
125
126
|
for emulator in installed_emulators:
|
|
126
127
|
logger.debug(f"installed_emulator: {emulator}")
|
|
127
|
-
self.
|
|
128
|
+
self.adb_connect(emulator.adb_address)
|
|
128
129
|
device_list = self.adb.device_list()
|
|
129
130
|
device_list = sorted(device_list, key=lambda x: x.serial)
|
|
130
131
|
adb_connected = []
|
|
@@ -27,25 +27,6 @@ class VBoxSerever(VBoxClass):
|
|
|
27
27
|
|
|
28
28
|
import ctypes
|
|
29
29
|
|
|
30
|
-
vbox_clsids = [
|
|
31
|
-
VBoxClass('{20190809-47b9-4a1e-82b2-07ccd5323c3f}', 'LDPlayer', 'ld'),
|
|
32
|
-
VBoxClass('{20191216-47b9-4a1e-82b2-07ccd5323c3f}', 'LDPlayer9', 'ld9'),
|
|
33
|
-
VBoxClass('{88888888-47b9-4a1e-82b2-07ccd5323c3f}', 'Nox', 'nox'),
|
|
34
|
-
VBoxClass('{baf3f651-58d8-429d-97ad-2b5699b43567}', 'BlueStacks', 'bstk'),
|
|
35
|
-
VBoxClass('{b1a7a4f2-47b9-4a1e-82b2-07ccd5323c3a}', 'Memu', 'memu'),
|
|
36
|
-
VBoxClass('{81919390-a492-11e5-a837-0800200c9a66}', 'MuMu', 'mumu'),
|
|
37
|
-
VBoxClass('{23cd1535-edaa-4f21-a4ab-45d97fd1d58b}', 'MuMu 12',
|
|
38
|
-
'mumu 12'),
|
|
39
|
-
# ('{B1A7A4F2-47B9-4A1E-82B2-07CCD5323C3F}', 'Oracle', 'oracle'), # nobody uses this
|
|
40
|
-
]
|
|
41
|
-
|
|
42
|
-
OpenProcess = ctypes.windll.kernel32.OpenProcess
|
|
43
|
-
OpenProcess.argtypes = [ctypes.c_uint32, ctypes.c_bool, ctypes.c_uint32]
|
|
44
|
-
OpenProcess.restype = ctypes.c_void_p
|
|
45
|
-
PROCESS_QUERY_INFORMATION = 0x0400
|
|
46
|
-
CloseHandle = ctypes.windll.kernel32.CloseHandle
|
|
47
|
-
CloseHandle.argtypes = [ctypes.c_void_p]
|
|
48
|
-
|
|
49
30
|
|
|
50
31
|
def get_server(clsid):
|
|
51
32
|
try:
|
|
@@ -60,6 +41,24 @@ def get_server(clsid):
|
|
|
60
41
|
|
|
61
42
|
# current process's privilege must equal to the target process's privilege, can raise a error if not
|
|
62
43
|
def installed_emulator():
|
|
44
|
+
vbox_clsids = [
|
|
45
|
+
VBoxClass('{20190809-47b9-4a1e-82b2-07ccd5323c3f}', 'LDPlayer', 'ld'),
|
|
46
|
+
VBoxClass('{20191216-47b9-4a1e-82b2-07ccd5323c3f}', 'LDPlayer9', 'ld9'),
|
|
47
|
+
VBoxClass('{88888888-47b9-4a1e-82b2-07ccd5323c3f}', 'Nox', 'nox'),
|
|
48
|
+
VBoxClass('{baf3f651-58d8-429d-97ad-2b5699b43567}', 'BlueStacks', 'bstk'),
|
|
49
|
+
VBoxClass('{b1a7a4f2-47b9-4a1e-82b2-07ccd5323c3a}', 'Memu', 'memu'),
|
|
50
|
+
VBoxClass('{81919390-a492-11e5-a837-0800200c9a66}', 'MuMu', 'mumu'),
|
|
51
|
+
VBoxClass('{23cd1535-edaa-4f21-a4ab-45d97fd1d58b}', 'MuMu 12',
|
|
52
|
+
'mumu 12'),
|
|
53
|
+
# ('{B1A7A4F2-47B9-4A1E-82B2-07CCD5323C3F}', 'Oracle', 'oracle'), # nobody uses this
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
OpenProcess = ctypes.windll.kernel32.OpenProcess
|
|
57
|
+
OpenProcess.argtypes = [ctypes.c_uint32, ctypes.c_bool, ctypes.c_uint32]
|
|
58
|
+
OpenProcess.restype = ctypes.c_void_p
|
|
59
|
+
PROCESS_QUERY_INFORMATION = 0x0400
|
|
60
|
+
CloseHandle = ctypes.windll.kernel32.CloseHandle
|
|
61
|
+
CloseHandle.argtypes = [ctypes.c_void_p]
|
|
63
62
|
logger.debug('enumerating vbox targets')
|
|
64
63
|
vbox_servers: list[VBoxSerever] = []
|
|
65
64
|
for vboxcls in vbox_clsids:
|
|
@@ -84,6 +83,7 @@ def installed_emulator():
|
|
|
84
83
|
|
|
85
84
|
logger.debug(f'running VirtualBox servers: {running_servers}')
|
|
86
85
|
results = []
|
|
86
|
+
server = ""
|
|
87
87
|
try:
|
|
88
88
|
for server in running_servers:
|
|
89
89
|
logger.debug(f'checking {server}')
|
|
@@ -34,3 +34,11 @@ class BaseWindowsCaptureMethod(BaseCaptureMethod):
|
|
|
34
34
|
|
|
35
35
|
def clickable(self):
|
|
36
36
|
return self.hwnd_window is not None and self.hwnd_window.visible
|
|
37
|
+
|
|
38
|
+
def __str__(self):
|
|
39
|
+
result = f'{self.__class__.__name__}_{self.width}x{self.height}'
|
|
40
|
+
if self.hwnd_window is None:
|
|
41
|
+
result += '_no_window'
|
|
42
|
+
else:
|
|
43
|
+
result += f'_{self.hwnd_window}'
|
|
44
|
+
return result
|
|
@@ -1,15 +1,18 @@
|
|
|
1
|
+
import subprocess
|
|
1
2
|
import sys
|
|
2
|
-
import traceback
|
|
3
3
|
import threading
|
|
4
|
+
import traceback
|
|
4
5
|
|
|
5
6
|
from ok.util.path import get_path_relative_to_exe
|
|
6
7
|
|
|
8
|
+
|
|
7
9
|
def get_thread_name(thread_id):
|
|
8
10
|
for thread in threading.enumerate():
|
|
9
11
|
if thread.ident == thread_id:
|
|
10
12
|
return thread.name
|
|
11
13
|
return "" # Return empty string if the thread name is not found
|
|
12
14
|
|
|
15
|
+
|
|
13
16
|
def dump_threads():
|
|
14
17
|
# Get the stack trace for each thread
|
|
15
18
|
thread_dumps = []
|
|
@@ -25,3 +28,4 @@ def dump_threads():
|
|
|
25
28
|
|
|
26
29
|
with open(output_file, "w") as file:
|
|
27
30
|
file.write("\n\n".join(thread_dumps))
|
|
31
|
+
subprocess.Popen(r'explorer /select,"{}"'.format(output_file))
|
|
@@ -8,6 +8,7 @@ from qfluentwidgets import FluentTranslator, qconfig, Theme
|
|
|
8
8
|
|
|
9
9
|
import ok
|
|
10
10
|
import ok.gui.resources
|
|
11
|
+
from ok.firebase.FireBaseAnalytics import FireBaseAnalytics
|
|
11
12
|
from ok.gui.Communicate import communicate
|
|
12
13
|
from ok.gui.MainWindow import MainWindow
|
|
13
14
|
from ok.gui.MessageWindow import MessageWindow
|
|
@@ -47,6 +48,8 @@ class App:
|
|
|
47
48
|
self.main_window = None
|
|
48
49
|
self.exit_event = exit_event
|
|
49
50
|
self.icon = QIcon(self.config.get('gui_icon') or ":/icon/icon.ico")
|
|
51
|
+
if self.config.get('firebase'):
|
|
52
|
+
self.fire_base_analytics = FireBaseAnalytics(self.config, self.exit_event)
|
|
50
53
|
|
|
51
54
|
translator = QTranslator(self.app)
|
|
52
55
|
full_path = os.path.join(i18n_path, f"{self.locale.name()}")
|
|
@@ -12,7 +12,7 @@ class Communicate(QObject):
|
|
|
12
12
|
task_info = Signal()
|
|
13
13
|
window = Signal(bool, int, int, int, int, int, int, float)
|
|
14
14
|
loading_progress = Signal(str)
|
|
15
|
-
notification = Signal(str, str, bool)
|
|
15
|
+
notification = Signal(str, str, bool, bool)
|
|
16
16
|
executor_paused: Signal = Signal(bool)
|
|
17
17
|
screenshot = Signal(np.ndarray, str)
|
|
18
18
|
update_overlay = Signal()
|
|
@@ -7,6 +7,7 @@ import ok.gui
|
|
|
7
7
|
from ok.capture.windows.dump import dump_threads
|
|
8
8
|
from ok.gui.Communicate import communicate
|
|
9
9
|
from ok.gui.about.AboutTab import AboutTab
|
|
10
|
+
from ok.gui.debug.DebugTab import DebugTab
|
|
10
11
|
from ok.gui.start.StartTab import StartTab
|
|
11
12
|
from ok.gui.tasks.OneTimeTaskTab import OneTimeTaskTab
|
|
12
13
|
from ok.gui.tasks.TriggerTaskTab import TriggerTaskTab
|
|
@@ -41,8 +42,13 @@ class MainWindow(MSFluentWindow):
|
|
|
41
42
|
# debug_tab = DebugTab()
|
|
42
43
|
# self.addSubInterface(debug_tab, FluentIcon.COMMAND_PROMPT, self.tr('Debug'))
|
|
43
44
|
# ... Add other tabs similarly
|
|
45
|
+
if debug:
|
|
46
|
+
debug_tab = DebugTab(exit_event)
|
|
47
|
+
self.addSubInterface(debug_tab, FluentIcon.DEVELOPER_TOOLS, self.tr('Debug'),
|
|
48
|
+
position=NavigationItemPosition.BOTTOM)
|
|
49
|
+
|
|
44
50
|
if about:
|
|
45
|
-
about_tab = AboutTab(icon, title, version, about)
|
|
51
|
+
about_tab = AboutTab(icon, title, version, debug, about)
|
|
46
52
|
self.addSubInterface(about_tab, FluentIcon.QUESTION, self.tr('About'),
|
|
47
53
|
position=NavigationItemPosition.BOTTOM)
|
|
48
54
|
# Styling the tabs and content if needed, for example:
|
|
@@ -82,7 +88,7 @@ class MainWindow(MSFluentWindow):
|
|
|
82
88
|
)
|
|
83
89
|
self.tray.showMessage(title, message)
|
|
84
90
|
|
|
85
|
-
def show_notification(self, message, title=None, error=
|
|
91
|
+
def show_notification(self, message, title=None, error=False, tray=True):
|
|
86
92
|
bar = InfoBar.error if error else InfoBar.info
|
|
87
93
|
if title is None:
|
|
88
94
|
title = f"{self.tr('Error') if error else 'Info'}:"
|
|
@@ -95,9 +101,8 @@ class MainWindow(MSFluentWindow):
|
|
|
95
101
|
duration=5000, # won't disappear automatically
|
|
96
102
|
parent=self.window()
|
|
97
103
|
)
|
|
98
|
-
if
|
|
99
|
-
|
|
100
|
-
self.tray.showMessage(title, message)
|
|
104
|
+
if tray:
|
|
105
|
+
self.tray.showMessage(title, message)
|
|
101
106
|
|
|
102
107
|
def capture_error(self):
|
|
103
108
|
self.show_notification(self.tr('Please check whether the game window is selected correctly!'),
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
from PySide6.QtCore import Qt
|
|
2
|
+
from PySide6.QtWidgets import QHBoxLayout, QLabel, QVBoxLayout
|
|
3
|
+
from qfluentwidgets import PushButton, InfoBar, InfoBarPosition
|
|
4
|
+
|
|
5
|
+
import ok.gui
|
|
6
|
+
from ok.gui.Communicate import communicate
|
|
7
|
+
from ok.gui.about.VersionCard import VersionCard
|
|
8
|
+
from ok.gui.widget.Tab import Tab
|
|
9
|
+
from ok.logging.Logger import get_logger
|
|
10
|
+
|
|
11
|
+
logger = get_logger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class AboutTab(Tab):
|
|
15
|
+
def __init__(self, icon, title, version, debug, about):
|
|
16
|
+
super().__init__()
|
|
17
|
+
self.version_card = VersionCard(icon, title, version, debug, self)
|
|
18
|
+
# Create a QTextEdit instance
|
|
19
|
+
self.addWidget(self.version_card)
|
|
20
|
+
about_label = QLabel()
|
|
21
|
+
about_label.setText(about)
|
|
22
|
+
about_label.setWordWrap(True)
|
|
23
|
+
about_label.setOpenExternalLinks(True)
|
|
24
|
+
|
|
25
|
+
# Set the layout on the widget
|
|
26
|
+
self.addWidget(about_label)
|
|
27
|
+
if ok.gui.app.updater.enabled():
|
|
28
|
+
self.download_latest_button = PushButton(self.tr('Download Release'))
|
|
29
|
+
self.download_latest_button.clicked.connect(self.download_latest)
|
|
30
|
+
self.download_latest_debug_button = PushButton(self.tr('Download Debug'))
|
|
31
|
+
self.download_latest_debug_button.clicked.connect(self.download_latest_debug)
|
|
32
|
+
|
|
33
|
+
self.latest_hbox = QHBoxLayout()
|
|
34
|
+
self.addLayout(self.latest_hbox)
|
|
35
|
+
self.latest_label = QLabel()
|
|
36
|
+
self.latest_label.setWordWrap(True)
|
|
37
|
+
self.latest_hbox.addWidget(self.latest_label, stretch=1)
|
|
38
|
+
self.download_latest_vbox = QVBoxLayout()
|
|
39
|
+
self.latest_hbox.addLayout(self.download_latest_vbox, stretch=0)
|
|
40
|
+
self.download_latest_vbox.addWidget(self.download_latest_button, stretch=0)
|
|
41
|
+
self.download_latest_vbox.addWidget(self.download_latest_debug_button, stretch=0)
|
|
42
|
+
self.download_latest_vbox.addStretch(1)
|
|
43
|
+
|
|
44
|
+
self.download_stable_button = PushButton(self.tr('Download Release'))
|
|
45
|
+
self.download_stable_button.clicked.connect(self.download_stable)
|
|
46
|
+
self.download_stable_debug_button = PushButton(self.tr('Download Debug'))
|
|
47
|
+
self.download_stable_debug_button.clicked.connect(self.download_stable_debug)
|
|
48
|
+
self.stable_hbox = QHBoxLayout()
|
|
49
|
+
self.stable_label = QLabel()
|
|
50
|
+
self.stable_label.setWordWrap(True)
|
|
51
|
+
self.addLayout(self.stable_hbox)
|
|
52
|
+
self.stable_hbox.addWidget(self.stable_label, stretch=1)
|
|
53
|
+
|
|
54
|
+
self.download_stable_vbox = QVBoxLayout()
|
|
55
|
+
self.stable_hbox.addLayout(self.download_stable_vbox, stretch=0)
|
|
56
|
+
self.download_stable_vbox.addWidget(self.download_stable_button, stretch=0)
|
|
57
|
+
self.download_stable_vbox.addWidget(self.download_stable_debug_button, stretch=0)
|
|
58
|
+
self.download_stable_vbox.addStretch(1)
|
|
59
|
+
|
|
60
|
+
communicate.download_update.connect(self.download_update)
|
|
61
|
+
communicate.check_update.connect(self.update_update)
|
|
62
|
+
|
|
63
|
+
self.update_update_buttons()
|
|
64
|
+
|
|
65
|
+
def update_update_buttons(self):
|
|
66
|
+
if ok.gui.app.updater.latest_release:
|
|
67
|
+
self.latest_label.setText(self.get_version_text(ok.gui.app.updater.latest_release))
|
|
68
|
+
has_release_asset = ok.gui.app.updater.latest_release is not None and ok.gui.app.updater.latest_release.get(
|
|
69
|
+
'release_asset') is not None
|
|
70
|
+
self.download_latest_button.setVisible(has_release_asset)
|
|
71
|
+
has_release_debug = ok.gui.app.updater.latest_release is not None and ok.gui.app.updater.latest_release.get(
|
|
72
|
+
'debug_asset') is not None
|
|
73
|
+
self.download_latest_debug_button.setVisible(has_release_debug)
|
|
74
|
+
self.latest_label.setVisible(has_release_asset or has_release_debug)
|
|
75
|
+
|
|
76
|
+
if ok.gui.app.updater.stable_release:
|
|
77
|
+
self.stable_label.setText(self.get_version_text(ok.gui.app.updater.stable_release))
|
|
78
|
+
|
|
79
|
+
has_release_asset = ok.gui.app.updater.stable_release is not None and ok.gui.app.updater.stable_release.get(
|
|
80
|
+
'release_asset') is not None
|
|
81
|
+
self.download_stable_button.setVisible(has_release_asset)
|
|
82
|
+
has_release_debug = ok.gui.app.updater.stable_release is not None and ok.gui.app.updater.stable_release.get(
|
|
83
|
+
'debug_asset') is not None
|
|
84
|
+
self.download_stable_debug_button.setVisible(has_release_debug)
|
|
85
|
+
self.stable_label.setVisible(has_release_asset or has_release_debug)
|
|
86
|
+
|
|
87
|
+
self.download_latest_button.setDisabled(ok.gui.app.updater.downloading)
|
|
88
|
+
self.download_stable_button.setDisabled(ok.gui.app.updater.downloading)
|
|
89
|
+
self.download_stable_debug_button.setDisabled(ok.gui.app.updater.downloading)
|
|
90
|
+
self.download_latest_debug_button.setDisabled(ok.gui.app.updater.downloading)
|
|
91
|
+
|
|
92
|
+
def update_update(self, error):
|
|
93
|
+
self.update_update_buttons()
|
|
94
|
+
|
|
95
|
+
def get_version_text(self, release):
|
|
96
|
+
text = "<h3>{title}: {version}</h3>"
|
|
97
|
+
if release.get('prerelease'):
|
|
98
|
+
title = self.tr('Beta Version')
|
|
99
|
+
else:
|
|
100
|
+
title = self.tr('Stable Version')
|
|
101
|
+
text = text.format(title=title, version=release.get('version'))
|
|
102
|
+
text += "<p>{date}</p>".format(date=release.get('date'))
|
|
103
|
+
text += "<p>{notes}</p>".format(notes=text_to_html_paragraphs(release.get('notes')))
|
|
104
|
+
return text
|
|
105
|
+
|
|
106
|
+
def download_update(self, percent, progress, done, error):
|
|
107
|
+
if done:
|
|
108
|
+
if error:
|
|
109
|
+
title = self.tr('Download Error:')
|
|
110
|
+
message = error
|
|
111
|
+
InfoBar.error(
|
|
112
|
+
title=title,
|
|
113
|
+
content=message,
|
|
114
|
+
orient=Qt.Horizontal,
|
|
115
|
+
isClosable=True,
|
|
116
|
+
position=InfoBarPosition.TOP,
|
|
117
|
+
duration=5000, # won't disappear automatically
|
|
118
|
+
parent=self
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
self.update_update_buttons()
|
|
122
|
+
|
|
123
|
+
@staticmethod
|
|
124
|
+
def download_latest():
|
|
125
|
+
ok.gui.app.updater.async_run(lambda: ok.gui.app.updater.download(ok.gui.app.updater.latest_release, False))
|
|
126
|
+
|
|
127
|
+
@staticmethod
|
|
128
|
+
def download_latest_debug():
|
|
129
|
+
ok.gui.app.updater.async_run(lambda: ok.gui.app.updater.download(ok.gui.app.updater.latest_release, True))
|
|
130
|
+
|
|
131
|
+
@staticmethod
|
|
132
|
+
def download_stable():
|
|
133
|
+
ok.gui.app.updater.async_run(lambda: ok.gui.app.updater.download(ok.gui.app.updater.stable_release, False))
|
|
134
|
+
|
|
135
|
+
@staticmethod
|
|
136
|
+
def download_stable_debug():
|
|
137
|
+
ok.gui.app.updater.async_run(lambda: ok.gui.app.updater.download(ok.gui.app.updater.stable_release, True))
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def text_to_html_paragraphs(text):
|
|
141
|
+
# Split the text into lines
|
|
142
|
+
lines = text.split('\n')
|
|
143
|
+
|
|
144
|
+
# Wrap each line in a <p> tag and join them
|
|
145
|
+
return ''.join(f'<p>{line}</p>' for line in lines)
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
from PySide6.QtCore import Qt
|
|
2
2
|
from PySide6.QtWidgets import QLabel
|
|
3
|
-
from qfluentwidgets import SettingCard, PushButton, ProgressBar, InfoBar, InfoBarPosition
|
|
3
|
+
from qfluentwidgets import SettingCard, PushButton, ProgressBar, InfoBar, InfoBarPosition, MessageBox
|
|
4
4
|
|
|
5
5
|
import ok
|
|
6
6
|
from ok.gui.Communicate import communicate
|
|
7
|
+
from ok.logging.Logger import get_logger
|
|
8
|
+
|
|
9
|
+
logger = get_logger(__name__)
|
|
7
10
|
|
|
8
11
|
|
|
9
12
|
class VersionCard(SettingCard):
|
|
10
13
|
""" Sample card """
|
|
11
14
|
|
|
12
|
-
def __init__(self, icon, title, version, parent=None):
|
|
13
|
-
super().__init__(icon, title, version)
|
|
15
|
+
def __init__(self, icon, title, version, debug, parent=None):
|
|
16
|
+
super().__init__(icon, title, f'{version} {self.get_type(debug)}')
|
|
14
17
|
self.downloading_text = QLabel()
|
|
15
18
|
self.hBoxLayout.addWidget(self.downloading_text)
|
|
16
19
|
self.hBoxLayout.addSpacing(16)
|
|
@@ -25,11 +28,17 @@ class VersionCard(SettingCard):
|
|
|
25
28
|
self.check_update_button.clicked.connect(self.check_update)
|
|
26
29
|
self.hBoxLayout.addWidget(self.check_update_button)
|
|
27
30
|
self.hBoxLayout.addSpacing(16)
|
|
31
|
+
self.update_button = PushButton()
|
|
32
|
+
self.update_button.clicked.connect(self.show_update_dialog)
|
|
33
|
+
self.hBoxLayout.addWidget(self.update_button)
|
|
34
|
+
self.hBoxLayout.addSpacing(16)
|
|
28
35
|
self.update_buttons(0, "")
|
|
29
36
|
communicate.check_update.connect(self.update_update)
|
|
30
37
|
communicate.download_update.connect(self.download_update)
|
|
31
38
|
|
|
32
39
|
def download_update(self, percent, progress, done, error):
|
|
40
|
+
if done and not error:
|
|
41
|
+
self.show_update_dialog()
|
|
33
42
|
self.update_buttons(percent, progress)
|
|
34
43
|
|
|
35
44
|
def update_buttons(self, percent, progress):
|
|
@@ -42,6 +51,33 @@ class VersionCard(SettingCard):
|
|
|
42
51
|
else:
|
|
43
52
|
self.downloading_text.hide()
|
|
44
53
|
self.download_bar.hide()
|
|
54
|
+
if ok.gui.app.updater.to_update:
|
|
55
|
+
self.update_button.setText(
|
|
56
|
+
self.tr('Update to {version} {type}').format(version=ok.gui.app.updater.to_update.get('version'),
|
|
57
|
+
type=self.get_type()))
|
|
58
|
+
self.update_button.setVisible(ok.gui.app.updater.to_update is not None)
|
|
59
|
+
|
|
60
|
+
def get_type(self, debug=None):
|
|
61
|
+
if debug is None and ok.gui.app.updater.to_update is not None:
|
|
62
|
+
debug = ok.gui.app.updater.to_update.get('debug')
|
|
63
|
+
return self.tr('Debug') if debug else self.tr('Release')
|
|
64
|
+
|
|
65
|
+
def show_update_dialog(self):
|
|
66
|
+
title = self.tr('Update Now')
|
|
67
|
+
content = self.tr(
|
|
68
|
+
"Are you sure you want to update to {version} {type}?".format(
|
|
69
|
+
version=ok.gui.app.updater.to_update.get(
|
|
70
|
+
'version'), type=self.get_type())) + '\n\n' + ok.gui.app.updater.to_update.get(
|
|
71
|
+
'notes')
|
|
72
|
+
|
|
73
|
+
w = MessageBox(title, content, self.window())
|
|
74
|
+
w.setContentCopyable(True)
|
|
75
|
+
if w.exec():
|
|
76
|
+
logger.info("user click update")
|
|
77
|
+
self.do_update()
|
|
78
|
+
|
|
79
|
+
def do_update(self):
|
|
80
|
+
ok.gui.app.updater.async_run(lambda: ok.gui.app.updater.update())
|
|
45
81
|
|
|
46
82
|
def update_update(self, error):
|
|
47
83
|
title = self.tr('Info')
|
|
@@ -67,6 +103,6 @@ class VersionCard(SettingCard):
|
|
|
67
103
|
self.check_update_button.setEnabled(True)
|
|
68
104
|
|
|
69
105
|
def check_update(self):
|
|
70
|
-
ok.gui.app.updater.
|
|
106
|
+
ok.gui.app.updater.check_for_updates()
|
|
71
107
|
self.check_update_button.setText(self.tr("Checking for updates"))
|
|
72
108
|
self.check_update_button.setEnabled(False)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
|
|
3
|
+
from PySide6.QtWidgets import QWidget
|
|
4
|
+
from qfluentwidgets import PushButton, FlowLayout
|
|
5
|
+
|
|
6
|
+
import ok.gui
|
|
7
|
+
from ok.capture.windows.dump import dump_threads
|
|
8
|
+
from ok.gui.widget.Tab import Tab
|
|
9
|
+
from ok.logging.Logger import get_logger
|
|
10
|
+
from ok.util.Handler import Handler
|
|
11
|
+
|
|
12
|
+
logger = get_logger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class DebugTab(Tab):
|
|
16
|
+
def __init__(self, exit_event):
|
|
17
|
+
super().__init__()
|
|
18
|
+
widget = QWidget()
|
|
19
|
+
layout = FlowLayout(widget, False)
|
|
20
|
+
|
|
21
|
+
layout.setContentsMargins(0, 0, 0, 0)
|
|
22
|
+
layout.setVerticalSpacing(20)
|
|
23
|
+
layout.setHorizontalSpacing(10)
|
|
24
|
+
self.addWidget(widget)
|
|
25
|
+
self.handler = Handler(exit_event, "DebugTab")
|
|
26
|
+
|
|
27
|
+
dump_button = PushButton(self.tr("Dump Threads(HotKey:Ctrl+Alt+D)"))
|
|
28
|
+
dump_button.clicked.connect(lambda: self.handler.post(dump_threads))
|
|
29
|
+
layout.addWidget(dump_button)
|
|
30
|
+
|
|
31
|
+
capture_button = PushButton(self.tr("Capture Screenshot"))
|
|
32
|
+
capture_button.clicked.connect(lambda: self.handler.post(self.capture))
|
|
33
|
+
layout.addWidget(capture_button)
|
|
34
|
+
|
|
35
|
+
open_log_folder = PushButton(self.tr("Open Logs"))
|
|
36
|
+
|
|
37
|
+
def capture(self):
|
|
38
|
+
if ok.gui.device_manager.capture_method is not None:
|
|
39
|
+
logger.info(f'ok.gui.device_manager.capture_method {ok.gui.device_manager.capture_method}')
|
|
40
|
+
capture = str(ok.gui.device_manager.capture_method)
|
|
41
|
+
frame = ok.gui.device_manager.capture_method.do_get_frame()
|
|
42
|
+
if frame is not None:
|
|
43
|
+
file_path = ok.gui.ok.screenshot.generate_screen_shot(frame, ok.gui.ok.screenshot.ui_dict,
|
|
44
|
+
ok.gui.ok.screenshot.screenshot_folder, capture)
|
|
45
|
+
|
|
46
|
+
# Use subprocess.Popen to open the file explorer and select the file
|
|
47
|
+
subprocess.Popen(r'explorer /select,"{}"'.format(file_path))
|
|
48
|
+
logger.info(f'captured screenshot: {capture}')
|
|
49
|
+
self.alert_info(self.tr('Capture Success'))
|
|
50
|
+
else:
|
|
51
|
+
self.alert_error(self.tr('Capture returned None'))
|
|
52
|
+
else:
|
|
53
|
+
self.alert_error(self.tr('No Capture Available or Selected'))
|
|
@@ -107,31 +107,35 @@ class Screenshot(QObject):
|
|
|
107
107
|
pil_image = self.to_pil_image(frame)
|
|
108
108
|
if pil_image is None:
|
|
109
109
|
return
|
|
110
|
-
|
|
110
|
+
|
|
111
|
+
originl_name = self.save_pil_image(name + '_original', folder, pil_image)
|
|
111
112
|
# Ensure no fill
|
|
112
113
|
draw = ImageDraw.Draw(pil_image)
|
|
113
114
|
|
|
114
115
|
frame_ratio = 1
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
116
|
+
if len(ui_dict) > 0:
|
|
117
|
+
for key, value in ui_dict.items():
|
|
118
|
+
boxes = value[0]
|
|
119
|
+
color = tuple([int(x) for x in value[2].getRgb()]) # Convert QColor to BGR tuple
|
|
120
|
+
for box in boxes:
|
|
121
|
+
width = int(box.width * frame_ratio)
|
|
122
|
+
height = int(box.height * frame_ratio)
|
|
123
|
+
if width <= 0 or height <= 0:
|
|
124
|
+
logger.error(f"box height and width <=0 {box}")
|
|
125
|
+
continue
|
|
126
|
+
x = int(box.x * frame_ratio)
|
|
127
|
+
y = int(box.y * frame_ratio)
|
|
128
|
+
# Draw a rectangle. Arguments are (x, y, width, height).
|
|
129
|
+
# Adjust these values according to the desired size and position.
|
|
130
|
+
draw.rectangle([x, y, x + width, y + height], outline=color, width=2)
|
|
131
|
+
# Put text
|
|
132
|
+
draw.text((x, y + height + 8), f"{box.name or key}_{round(box.confidence * 100)}", fill=color,
|
|
133
|
+
font=self.pil_font)
|
|
134
|
+
self.save_pil_image(name + '_boxed', folder, pil_image)
|
|
135
|
+
return originl_name
|
|
136
|
+
|
|
137
|
+
@staticmethod
|
|
138
|
+
def save_pil_image(name, folder, pil_image):
|
|
135
139
|
|
|
136
140
|
now = datetime.now()
|
|
137
141
|
|
|
@@ -145,7 +149,9 @@ class Screenshot(QObject):
|
|
|
145
149
|
try:
|
|
146
150
|
pil_image.save(file)
|
|
147
151
|
except OSError:
|
|
148
|
-
|
|
152
|
+
file = os.path.join(folder, f"{time_string}.png")
|
|
153
|
+
pil_image.save(file)
|
|
154
|
+
return file
|
|
149
155
|
|
|
150
156
|
def stop(self):
|
|
151
157
|
logger.debug(f'stop screenshot')
|