ok-script 0.0.7__py3-none-any.whl

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 (122) hide show
  1. autohelper/AutoHelper.py +116 -0
  2. autohelper/__init__.py +0 -0
  3. autohelper/capture/BaseCaptureMethod.py +30 -0
  4. autohelper/capture/HwndWindow.py +138 -0
  5. autohelper/capture/__init__.py +0 -0
  6. autohelper/capture/adb/ADBCaptureMethod.py +29 -0
  7. autohelper/capture/adb/DeviceManager.py +209 -0
  8. autohelper/capture/adb/__init__.py +0 -0
  9. autohelper/capture/adb/bin/__init__.py +0 -0
  10. autohelper/capture/adb/targets.py +61 -0
  11. autohelper/capture/adb/vbox.py +140 -0
  12. autohelper/capture/windows/WindowsGraphicsCaptureMethod.py +228 -0
  13. autohelper/capture/windows/__init__.py +0 -0
  14. autohelper/capture/windows/d3d11.py +74 -0
  15. autohelper/capture/windows/utils.py +149 -0
  16. autohelper/capture/windows/window.py +36 -0
  17. autohelper/color/Color.py +41 -0
  18. autohelper/color/__init__.py +0 -0
  19. autohelper/config/Config.py +79 -0
  20. autohelper/config/InfoDict.py +16 -0
  21. autohelper/config/__init__.py +0 -0
  22. autohelper/feature/Box.py +199 -0
  23. autohelper/feature/Feature.py +20 -0
  24. autohelper/feature/FeatureSet.py +207 -0
  25. autohelper/feature/FindFeature.py +52 -0
  26. autohelper/feature/__init__.py +0 -0
  27. autohelper/gui/App.py +120 -0
  28. autohelper/gui/Communicate.py +22 -0
  29. autohelper/gui/MainWindow.py +69 -0
  30. autohelper/gui/TabTitles.py +56 -0
  31. autohelper/gui/__init__.py +5 -0
  32. autohelper/gui/debug/AspectRatioWidget.py +31 -0
  33. autohelper/gui/debug/DebugTab.py +37 -0
  34. autohelper/gui/debug/FrameWidget.py +125 -0
  35. autohelper/gui/debug/InfoWidget.py +40 -0
  36. autohelper/gui/debug/LoggerWidget.py +74 -0
  37. autohelper/gui/debug/__init__.py +0 -0
  38. autohelper/gui/i18n/__init__.py +0 -0
  39. autohelper/gui/i18n/path.py +3 -0
  40. autohelper/gui/icon/__init__.py +0 -0
  41. autohelper/gui/icon/icon.py +6 -0
  42. autohelper/gui/loading/LoadingWindow.py +142 -0
  43. autohelper/gui/loading/__init__.py +0 -0
  44. autohelper/gui/overlay/OverlayWindow.py +34 -0
  45. autohelper/gui/overlay/__init__.py +0 -0
  46. autohelper/gui/resources.py +485 -0
  47. autohelper/gui/tasks/ConfigItemFactory.py +14 -0
  48. autohelper/gui/tasks/StartButton.py +47 -0
  49. autohelper/gui/tasks/TaskOpButton.py +33 -0
  50. autohelper/gui/tasks/TaskTab.py +121 -0
  51. autohelper/gui/tasks/TooltipTableWidget.py +39 -0
  52. autohelper/gui/tasks/__init__.py +0 -0
  53. autohelper/gui/util/Alert.py +20 -0
  54. autohelper/gui/util/InitWorker.py +17 -0
  55. autohelper/gui/util/__init__.py +0 -0
  56. autohelper/gui/widget/ListTableWidgetItem.py +27 -0
  57. autohelper/gui/widget/NumericTableWidgetItem.py +33 -0
  58. autohelper/gui/widget/RoundCornerContainer.py +59 -0
  59. autohelper/gui/widget/TabWidget.py +30 -0
  60. autohelper/gui/widget/UpdateConfigWidgetItem.py +16 -0
  61. autohelper/gui/widget/YesNonWidgetItem.py +23 -0
  62. autohelper/gui/widget/__init__.py +0 -0
  63. autohelper/interaction/ADBInteraction.py +33 -0
  64. autohelper/interaction/BaseInteraction.py +36 -0
  65. autohelper/interaction/Win32Interaction.py +56 -0
  66. autohelper/interaction/__init__.py +0 -0
  67. autohelper/logging/Logger.py +103 -0
  68. autohelper/logging/__init__.py +0 -0
  69. autohelper/ocr/OCR.py +50 -0
  70. autohelper/ocr/__init__.py +0 -0
  71. autohelper/predict/__init__.py +0 -0
  72. autohelper/predict/predict.py +45 -0
  73. autohelper/rotypes/Windows/Foundation/Collections.py +60 -0
  74. autohelper/rotypes/Windows/Foundation/__init__.py +153 -0
  75. autohelper/rotypes/Windows/Globalization/__init__.py +25 -0
  76. autohelper/rotypes/Windows/Graphics/Capture/__init__.py +110 -0
  77. autohelper/rotypes/Windows/Graphics/DirectX/Direct3D11/__init__.py +41 -0
  78. autohelper/rotypes/Windows/Graphics/DirectX/__init__.py +167 -0
  79. autohelper/rotypes/Windows/Graphics/Imaging/__init__.py +34 -0
  80. autohelper/rotypes/Windows/Graphics/__init__.py +5 -0
  81. autohelper/rotypes/Windows/Media/Ocr/__init__.py +76 -0
  82. autohelper/rotypes/Windows/Media/__init__.py +0 -0
  83. autohelper/rotypes/Windows/Security/Cryptography/__init__.py +18 -0
  84. autohelper/rotypes/Windows/Security/__init__.py +0 -0
  85. autohelper/rotypes/Windows/Storage/Streams/__init__.py +27 -0
  86. autohelper/rotypes/Windows/Storage/__init__.py +0 -0
  87. autohelper/rotypes/Windows/__init__.py +0 -0
  88. autohelper/rotypes/__init__.py +4 -0
  89. autohelper/rotypes/delegate.py +105 -0
  90. autohelper/rotypes/export.py +21 -0
  91. autohelper/rotypes/idldsl.py +272 -0
  92. autohelper/rotypes/inspectable.py +79 -0
  93. autohelper/rotypes/roapi.py +30 -0
  94. autohelper/rotypes/types.py +77 -0
  95. autohelper/rotypes/winstring.py +44 -0
  96. autohelper/save/BlackBarProcessor.py +25 -0
  97. autohelper/save/PostProcessor.py +6 -0
  98. autohelper/save/SaveByInterval.py +30 -0
  99. autohelper/save/SaveByKeyPress.py +27 -0
  100. autohelper/save/SaveMethodBase.py +46 -0
  101. autohelper/save/__init__.py +0 -0
  102. autohelper/scene/FeatureScene.py +14 -0
  103. autohelper/scene/Scene.py +21 -0
  104. autohelper/scene/__init__.py +0 -0
  105. autohelper/stats/StreamStats.py +34 -0
  106. autohelper/stats/__init__.py +0 -0
  107. autohelper/task/BaseTask.py +109 -0
  108. autohelper/task/ExecutorOperation.py +119 -0
  109. autohelper/task/FindFeatureTask.py +6 -0
  110. autohelper/task/TaskExecutor.py +249 -0
  111. autohelper/task/__init__.py +0 -0
  112. autohelper/util/__init__.py +0 -0
  113. autohelper/util/json.py +27 -0
  114. autohelper/util/list.py +2 -0
  115. autohelper/util/path.py +37 -0
  116. autohelper/util/thread.py +12 -0
  117. autohelper/util/win32_process.py +86 -0
  118. autohelper/util/yaml.py +28 -0
  119. ok_script-0.0.7.dist-info/METADATA +64 -0
  120. ok_script-0.0.7.dist-info/RECORD +122 -0
  121. ok_script-0.0.7.dist-info/WHEEL +5 -0
  122. ok_script-0.0.7.dist-info/top_level.txt +1 -0
@@ -0,0 +1,47 @@
1
+ from PySide6.QtCore import Slot, QPropertyAnimation
2
+ from PySide6.QtGui import QColor
3
+ from PySide6.QtWidgets import QPushButton
4
+
5
+ import autohelper
6
+ from autohelper.gui.Communicate import communicate
7
+ from autohelper.gui.util.Alert import show_alert
8
+ from autohelper.logging.Logger import get_logger
9
+
10
+ logger = get_logger(__name__)
11
+
12
+
13
+ class StartButton(QPushButton):
14
+ def __init__(self):
15
+ super().__init__("Start")
16
+ self.setCheckable(True)
17
+ self.clicked.connect(self.toggle_text)
18
+ self.animation = QPropertyAnimation(self, b"color")
19
+ self.update_paused(True)
20
+ communicate.executor_paused.connect(self.update_paused)
21
+
22
+ def update_paused(self, paused):
23
+ if paused:
24
+ self.setText(self.tr("Start All"))
25
+ self.setChecked(False)
26
+ self.animation.stop()
27
+ else:
28
+ self.setText(self.tr("Pause All"))
29
+ self.setChecked(True)
30
+ self.start_animation()
31
+
32
+ @Slot()
33
+ def toggle_text(self):
34
+ if self.isChecked():
35
+ logger.info("Click Start Executor")
36
+ if not autohelper.gui.executor.start():
37
+ show_alert("Error", "No Task to Run, Please Enable Task First!")
38
+ self.setChecked(False)
39
+ else:
40
+ logger.info("Click Pause Executor")
41
+ autohelper.gui.executor.pause()
42
+
43
+ def start_animation(self):
44
+ self.animation.setStartValue(QColor(0, 0, 0))
45
+ self.animation.setEndValue(QColor(255, 255, 255))
46
+ self.animation.setDuration(1000)
47
+ self.animation.start()
@@ -0,0 +1,33 @@
1
+ from PySide6.QtCore import Slot
2
+ from PySide6.QtWidgets import QPushButton
3
+
4
+ from autohelper.logging.Logger import get_logger
5
+ from autohelper.task.BaseTask import BaseTask
6
+
7
+ logger = get_logger(__name__)
8
+
9
+
10
+ class TaskOpButton(QPushButton):
11
+ def __init__(self, task: BaseTask):
12
+ super().__init__("Enable")
13
+ self.clicked.connect(self.toggle_text)
14
+ self.task = task
15
+
16
+ def update_task(self, task: BaseTask):
17
+ if task.enabled:
18
+ if task.done:
19
+ self.setText(self.tr("Rerun"))
20
+ else:
21
+ self.setText(self.tr("Disable"))
22
+ else:
23
+ self.setText(self.tr("Enable"))
24
+
25
+ @Slot()
26
+ def toggle_text(self):
27
+ if self.task.enabled:
28
+ if self.task.done:
29
+ self.task.enable()
30
+ else:
31
+ self.task.disable()
32
+ else:
33
+ self.task.disable()
@@ -0,0 +1,121 @@
1
+ from typing import List
2
+
3
+ from PySide6.QtCore import Qt, QTimer
4
+ from PySide6.QtGui import QColor
5
+ from PySide6.QtWidgets import QTableWidget, QTableWidgetItem, QVBoxLayout, QWidget, QHBoxLayout
6
+
7
+ from autohelper.gui.Communicate import communicate
8
+ from autohelper.gui.tasks.ConfigItemFactory import config_widget_item
9
+ from autohelper.gui.tasks.StartButton import StartButton
10
+ from autohelper.gui.tasks.TaskOpButton import TaskOpButton
11
+ from autohelper.gui.tasks.TooltipTableWidget import TooltipTableWidget
12
+ from autohelper.gui.widget.RoundCornerContainer import RoundCornerContainer
13
+ from autohelper.gui.widget.UpdateConfigWidgetItem import value_to_string
14
+ from autohelper.logging.Logger import get_logger
15
+ from autohelper.task.BaseTask import BaseTask
16
+
17
+ logger = get_logger(__name__)
18
+
19
+
20
+ class TaskTab(QWidget):
21
+ def __init__(self, tasks: List[BaseTask]):
22
+ super().__init__()
23
+
24
+ self.mainLayout = QVBoxLayout(self)
25
+ self.setLayout(self.mainLayout)
26
+ self.tasks = tasks
27
+ # Top row setup with horizontal splitter
28
+ self.top_layout = QHBoxLayout()
29
+ self.task_table = TooltipTableWidget([0.7, 0.15, 0.15])
30
+ self.task_container = RoundCornerContainer(self.tr('Tasks'), self.task_table)
31
+ self.start_button = StartButton()
32
+ self.task_container.add_top_widget(self.start_button)
33
+
34
+ self.top_layout.addWidget(self.task_container)
35
+ self.task_labels = [self.tr('Name'), self.tr('Status'), self.tr('Operation')]
36
+ self.create_table()
37
+ self.mainLayout.addLayout(self.top_layout)
38
+
39
+ self.task_config_table = TooltipTableWidget([0.3, 0.7])
40
+ self.task_config_container = RoundCornerContainer(self.tr('Tasks Config'), self.task_config_table)
41
+ self.task_config_labels = [self.tr('Config'), self.tr('Value')]
42
+ self.task_config_table.setColumnCount(len(self.task_config_labels)) # Name and Value
43
+ self.task_config_table.setHorizontalHeaderLabels(self.task_config_labels)
44
+ self.update_config_table()
45
+ self.mainLayout.addWidget(self.task_config_container)
46
+
47
+ self.task_info_table = TooltipTableWidget([0.3, 0.7])
48
+ self.task_info_container = RoundCornerContainer(self.tr('Tasks Info'), self.task_info_table)
49
+ self.top_layout.addWidget(self.task_info_container)
50
+ self.task_info_labels = [self.tr('Info'), self.tr('Value')]
51
+ self.task_info_table.setColumnCount(len(self.task_info_labels)) # Name and Value
52
+ self.task_info_table.setHorizontalHeaderLabels(self.task_config_labels)
53
+ self.update_info_table()
54
+
55
+ communicate.tasks.connect(self.update_table)
56
+ communicate.task_info.connect(self.update_info_table)
57
+ self.timer = QTimer()
58
+ self.timer.timeout.connect(self.update_info_table)
59
+ self.timer.timeout.connect(self.update_table)
60
+ self.timer.start(1000)
61
+
62
+ def update_config_table(self):
63
+ task = self.tasks[self.task_table.selectedIndexes()[0].row()]
64
+ config = task.config
65
+ self.task_config_container.title_label.setText(f"{self.tr('Config')}: {task.name}")
66
+ self.task_config_table.setRowCount(len(config))
67
+ for row, (key, value) in enumerate(config.items()):
68
+ if not self.task_config_table.item(row, 0):
69
+ item0 = self.uneditable_item()
70
+ self.task_config_table.setItem(row, 0, item0)
71
+ self.task_config_table.item(row, 0).setText(key)
72
+ config_widget_item(self.task_config_table, row, 1, config, key, value)
73
+
74
+ def update_info_table(self):
75
+ task = self.tasks[self.task_table.selectedIndexes()[0].row()]
76
+ info = task.info
77
+ self.task_info_container.title_label.setText(f"{self.tr('Info')}: {task.name}")
78
+ self.task_info_table.setRowCount(len(info))
79
+ for row, (key, value) in enumerate(info.items()):
80
+ if not self.task_info_table.item(row, 0):
81
+ item0 = self.uneditable_item()
82
+ self.task_info_table.setItem(row, 0, item0)
83
+ self.task_info_table.item(row, 0).setText(key)
84
+ if not self.task_info_table.item(row, 1):
85
+ item1 = self.uneditable_item()
86
+ self.task_info_table.setItem(row, 1, item1)
87
+ self.task_info_table.item(row, 1).setText(value_to_string(value))
88
+
89
+ def create_table(self):
90
+ self.task_table.setRowCount(len(self.tasks)) # Adjust the row count to match the number of attributes
91
+ self.task_table.setColumnCount(len(self.task_labels)) # Name and Value
92
+ self.task_table.setHorizontalHeaderLabels(self.task_labels)
93
+ self.task_table.setSelectionBehavior(QTableWidget.SelectRows)
94
+ self.task_table.setSelectionMode(QTableWidget.SingleSelection)
95
+ self.task_table.selectRow(0)
96
+ self.task_table.itemSelectionChanged.connect(self.update_config_table)
97
+ for row, task in enumerate(self.tasks):
98
+ for i in range(2):
99
+ item = self.uneditable_item()
100
+ self.task_table.setItem(row, i, item)
101
+ op_button = TaskOpButton(task)
102
+ self.task_table.setCellWidget(row, 2, op_button)
103
+ self.update_table()
104
+
105
+ def uneditable_item(self):
106
+ item = QTableWidgetItem()
107
+ item.setFlags(item.flags() & ~Qt.ItemIsEditable)
108
+ return item
109
+
110
+ def update_table(self):
111
+ for row, task in enumerate(self.tasks):
112
+ self.task_table.item(row, 0).setText(task.name)
113
+ status = task.get_status()
114
+ self.task_table.item(row, 1).setText(self.tr(status))
115
+ if status == "Running":
116
+ self.task_table.item(row, 1).setBackground(QColor("green"))
117
+ elif status == "Disabled":
118
+ self.task_table.item(row, 1).setBackground(QColor("red"))
119
+ else:
120
+ self.task_table.item(row, 1).setBackground(QColor(0, 0, 0, 0))
121
+ self.task_table.cellWidget(row, 2).update_task(task)
@@ -0,0 +1,39 @@
1
+ from PySide6.QtCore import QEvent
2
+ from PySide6.QtWidgets import QTableWidget, QToolTip, QHeaderView
3
+
4
+
5
+ class TooltipTableWidget(QTableWidget):
6
+
7
+ def __init__(self, width_percentages=None):
8
+ super().__init__()
9
+ self.verticalHeader().setVisible(False)
10
+ self.width_percentages = width_percentages
11
+
12
+ # Set the QTableWidget to fill the width of its parent
13
+ self.horizontalHeader().setStretchLastSection(True)
14
+
15
+ # Set the columns to resize to fill the width of the QTableWidget
16
+ self.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
17
+ self.setWordWrap(True)
18
+
19
+ def setItem(self, row, column, item):
20
+ super().setItem(row, column, item)
21
+
22
+ def resizeEvent(self, event):
23
+ if self.width_percentages is not None:
24
+ width = self.width() - self.verticalScrollBar().width()
25
+ for i, percentage in enumerate(self.width_percentages):
26
+ self.setColumnWidth(i, int(width * percentage))
27
+ super().resizeEvent(event)
28
+
29
+ def viewportEvent(self, event):
30
+ if event.type() == QEvent.ToolTip:
31
+ pos = event.pos()
32
+ item = self.itemAt(pos)
33
+ if item:
34
+ if self.visualItemRect(item).width() < self.fontMetrics().horizontalAdvance(item.text()):
35
+ QToolTip.showText(event.globalPos(), item.text(), self)
36
+ else:
37
+ QToolTip.hideText()
38
+ return True
39
+ return super().viewportEvent(event)
File without changes
@@ -0,0 +1,20 @@
1
+ from PySide6.QtWidgets import QMessageBox
2
+
3
+ import autohelper
4
+
5
+
6
+ def show_alert(title, message):
7
+ # Create a QMessageBox
8
+ msg = QMessageBox()
9
+
10
+ # Set the title and message
11
+ msg.setWindowTitle(title)
12
+ msg.setText(message)
13
+
14
+ msg.setWindowIcon(autohelper.gui.app.icon)
15
+
16
+ # Add a confirm button
17
+ msg.setStandardButtons(QMessageBox.Ok)
18
+
19
+ # Show the message box
20
+ msg.exec()
@@ -0,0 +1,17 @@
1
+ from PySide6.QtCore import QThread
2
+
3
+ from autohelper.gui.Communicate import communicate
4
+ from autohelper.logging.Logger import get_logger
5
+
6
+ logger = get_logger(__name__)
7
+
8
+
9
+ class InitWorker(QThread):
10
+
11
+ def __init__(self, fun):
12
+ super().__init__()
13
+ self.fun = fun
14
+
15
+ def run(self):
16
+ self.fun()
17
+ communicate.init.emit(True, "")
File without changes
@@ -0,0 +1,27 @@
1
+ from PySide6.QtCore import Qt
2
+ from PySide6.QtWidgets import QTableWidgetItem
3
+
4
+ from autohelper.gui.widget.UpdateConfigWidgetItem import UpdateConfigWidgetItem, value_to_string
5
+
6
+
7
+ class ListTableWidgetItem(UpdateConfigWidgetItem, QTableWidgetItem):
8
+
9
+ def __init__(self, config, key, value, parent=None):
10
+ UpdateConfigWidgetItem.__init__(self, config, key, value)
11
+ QTableWidgetItem.__init__(self)
12
+ self.setText(value_to_string(value))
13
+
14
+ def setData(self, role, value):
15
+ if role == Qt.EditRole:
16
+ list_value = convert_to_list(value)
17
+ self.set_value(list_value)
18
+ self.setText(value_to_string(list_value))
19
+ super().setData(role, value)
20
+
21
+
22
+ def convert_to_list(s):
23
+ # Replace the Chinese comma with the English comma
24
+ s = s.replace(",", ",")
25
+
26
+ # Split the string by comma and strip the white spaces
27
+ return [item.strip() for item in s.split(",")]
@@ -0,0 +1,33 @@
1
+ from PySide6.QtCore import Qt
2
+ from PySide6.QtGui import QIntValidator, QDoubleValidator
3
+ from PySide6.QtWidgets import QTableWidgetItem
4
+
5
+ from autohelper.gui.widget.UpdateConfigWidgetItem import UpdateConfigWidgetItem, value_to_string
6
+
7
+
8
+ class NumericTableWidgetItem(UpdateConfigWidgetItem, QTableWidgetItem):
9
+
10
+ def __init__(self, config, key, value, parent=None):
11
+ UpdateConfigWidgetItem.__init__(self, config, key, value)
12
+ QTableWidgetItem.__init__(self)
13
+
14
+ # Determine if the original value is int or float
15
+ if isinstance(value, int):
16
+ self.validator = QIntValidator(0, 999999, self.tableWidget())
17
+ elif isinstance(value, float):
18
+ self.validator = QDoubleValidator(0, 999999, 2, self.tableWidget())
19
+ else:
20
+ raise ValueError("Value must be an int or float")
21
+ self.setText(value_to_string(value))
22
+
23
+ def setData(self, role, value):
24
+ if role == Qt.EditRole:
25
+ state, _, _ = self.validator.validate(str(value), 0)
26
+ if state != QIntValidator.Acceptable:
27
+ return
28
+ if isinstance(self.value, int):
29
+ value = int(value)
30
+ else:
31
+ value = float(value)
32
+ self.set_value(value)
33
+ super().setData(role, value)
@@ -0,0 +1,59 @@
1
+ from PySide6.QtGui import QPalette
2
+ from PySide6.QtWidgets import QVBoxLayout, QLabel, QFrame, QSizePolicy, QLayout, QWidget, QHBoxLayout, QSpacerItem
3
+
4
+
5
+ class RoundCornerContainer(QFrame):
6
+ def __init__(self, title, child=None, parent=None):
7
+ super(RoundCornerContainer, self).__init__(parent)
8
+
9
+ # Set the layout
10
+ self.top_layout = QHBoxLayout()
11
+ layout = QVBoxLayout(self)
12
+ self.title_label = QLabel(title)
13
+ self.title_label.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
14
+ self.top_layout.addWidget(self.title_label)
15
+ self.top_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum))
16
+ layout.addLayout(self.top_layout)
17
+ if child is not None and isinstance(child, QWidget):
18
+ child.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
19
+ layout.addWidget(child)
20
+ elif child is not None and isinstance(child, QLayout):
21
+ child.setSizeConstraint(QVBoxLayout.SetMaximumSize)
22
+ layout.addLayout(child)
23
+ layout.setStretchFactor(child, 1)
24
+ layout.setStretchFactor(self.title_label, 0)
25
+
26
+ self.setLayout(layout)
27
+
28
+ self.setFrameStyle(QFrame.Panel | QFrame.Raised)
29
+ self.setLineWidth(2)
30
+
31
+ color = self.get_palette_color(QPalette.Base)
32
+ self.setStyleSheet(f"background-color:{color};")
33
+
34
+ def add_top_widget(self, widget):
35
+ self.top_layout.addWidget(widget)
36
+
37
+ def get_palette_color(self, palette_color):
38
+ palette = self.palette()
39
+ return color_to_hex(palette.color(palette_color))
40
+
41
+
42
+ def color_to_hex(color):
43
+ """Converts a QColor object to a hex string representation.
44
+
45
+ Args:
46
+ color: The QColor object to convert.
47
+
48
+ Returns:
49
+ A string representing the hex code of the color (e.g., "#FF0000" for red).
50
+ """
51
+ red = color.red()
52
+ green = color.green()
53
+ blue = color.blue()
54
+ hex_color = f"#{red:02X}{green:02X}{blue:02X}"
55
+ return hex_color
56
+
57
+ # Usage:
58
+ # widget = RoundCornerContainer("Title")
59
+ # widget.show()
@@ -0,0 +1,30 @@
1
+ from PySide6.QtGui import QPalette
2
+ from PySide6.QtWidgets import QWidget
3
+
4
+
5
+ class TabWidget(QWidget):
6
+
7
+ def __init__(self):
8
+ super().__init__()
9
+ color = self.get_palette_color(QPalette.Base)
10
+ self.setStyleSheet(f"background-color:{color};")
11
+
12
+ def get_palette_color(self, palette_color):
13
+ palette = self.palette()
14
+ return color_to_hex(palette.color(palette_color))
15
+
16
+
17
+ def color_to_hex(color):
18
+ """Converts a QColor object to a hex string representation.
19
+
20
+ Args:
21
+ color: The QColor object to convert.
22
+
23
+ Returns:
24
+ A string representing the hex code of the color (e.g., "#FF0000" for red).
25
+ """
26
+ red = color.red()
27
+ green = color.green()
28
+ blue = color.blue()
29
+ hex_color = f"#{red:02X}{green:02X}{blue:02X}"
30
+ return hex_color
@@ -0,0 +1,16 @@
1
+ class UpdateConfigWidgetItem:
2
+ def __init__(self, config, key, value):
3
+ self.key = key
4
+ self.config = config
5
+ self.value = value
6
+
7
+ def set_value(self, value):
8
+ self.config[self.key] = value
9
+ self.value = value
10
+
11
+
12
+ def value_to_string(obj):
13
+ if isinstance(obj, list):
14
+ return ', '.join(map(str, obj))
15
+ else:
16
+ return str(obj)
@@ -0,0 +1,23 @@
1
+ from PySide6.QtWidgets import QComboBox
2
+
3
+ from autohelper.gui.widget.UpdateConfigWidgetItem import UpdateConfigWidgetItem
4
+
5
+
6
+ class YesNonWidgetItem(UpdateConfigWidgetItem, QComboBox):
7
+
8
+ def __init__(self, config, key, value):
9
+ UpdateConfigWidgetItem.__init__(self, config, key, value)
10
+ QComboBox.__init__(self)
11
+ self.addItems(["Yes", "No"])
12
+ if value:
13
+ self.setCurrentIndex(0)
14
+ else:
15
+ self.setCurrentIndex(1)
16
+
17
+ self.currentIndexChanged.connect(self.index_changed)
18
+
19
+ def index_changed(self, index):
20
+ if index == 0:
21
+ self.set_value(True)
22
+ else:
23
+ self.set_value(False)
File without changes
@@ -0,0 +1,33 @@
1
+ from autohelper.interaction.BaseInteraction import BaseInteraction
2
+ from autohelper.logging.Logger import get_logger
3
+
4
+ logger = get_logger(__name__)
5
+
6
+
7
+ class ADBBaseInteraction(BaseInteraction):
8
+
9
+ def __init__(self, device_manager, capture):
10
+ super().__init__(capture)
11
+ self.device_manager = device_manager
12
+ logger.info(f"width: {self.width}, height: {self.height}")
13
+ if self.width == 0 or self.height == 0:
14
+ logger.warning(f"Could not parse screen resolution.")
15
+ # raise RuntimeError(f"ADBBaseInteraction: Could not parse screen resolution.")
16
+
17
+ @property
18
+ def width(self):
19
+ return self.device_manager.width
20
+
21
+ @property
22
+ def height(self):
23
+ return self.device_manager.height
24
+
25
+ def send_key(self, key, down_time=0.02):
26
+ super().send_key(key, down_time)
27
+ self.device_manager.device.shell(f"input keyevent {key}")
28
+
29
+ def click(self, x=-1, y=-1):
30
+ super().click(x, y)
31
+ x = int(x * self.width / self.capture.width)
32
+ y = int(y * self.height / self.capture.height)
33
+ self.device_manager.device.shell(f"input tap {x} {y}")
@@ -0,0 +1,36 @@
1
+ from autohelper.feature.Box import Box
2
+ from autohelper.gui.Communicate import communicate
3
+ from autohelper.logging.Logger import get_logger
4
+
5
+ logger = get_logger(__name__)
6
+
7
+
8
+ class BaseInteraction:
9
+
10
+ def __init__(self, capture):
11
+ self.capture = capture
12
+
13
+ def should_capture(self):
14
+ return True
15
+
16
+ def send_key(self, key, down_time=0.02):
17
+ pass
18
+
19
+ def move(self, x, y):
20
+ pass
21
+
22
+ def click_relative(self, x, y):
23
+ self.click(int(self.capture.width * x), int(self.capture.height * y))
24
+
25
+ def move_relative(self, x, y):
26
+ self.move(int(self.capture.width * x), int(self.capture.height * y))
27
+
28
+ def click_box(self, box: Box, relative_x=0.5, relative_y=0.5):
29
+ logger.info(f"click_box {box}")
30
+ x, y = box.relative_with_variance(relative_x, relative_y)
31
+ self.click(x, y)
32
+
33
+ def click(self, x=-1, y=-1):
34
+ logger.info(f"click {x, y}")
35
+ communicate.draw_box.emit("click", [Box(max(0, x - 10), max(0, y - 10), 20, 20, name="click")], "green")
36
+ pass
@@ -0,0 +1,56 @@
1
+ import ctypes
2
+ import time
3
+
4
+ import pydirectinput
5
+
6
+ from autohelper.capture.BaseCaptureMethod import BaseCaptureMethod
7
+ from autohelper.interaction.BaseInteraction import BaseInteraction
8
+ from autohelper.logging.Logger import get_logger
9
+
10
+ logger = get_logger(__name__)
11
+
12
+
13
+ class Win32Interaction(BaseInteraction):
14
+
15
+ def __init__(self, capture: BaseCaptureMethod):
16
+ super().__init__(capture)
17
+ self.post = ctypes.windll.user32.PostMessageW
18
+ if not is_admin():
19
+ logger.error(f"You must be an admin to use Win32Interaction")
20
+
21
+ def send_key(self, key, down_time=0.02):
22
+ if not self.capture.clickable():
23
+ return
24
+ pydirectinput.keyDown(key)
25
+ time.sleep(down_time)
26
+ pydirectinput.keyUp(key)
27
+
28
+ def move(self, x, y):
29
+ if not self.capture.clickable():
30
+ return
31
+ x, y = self.capture.get_abs_cords(x, y)
32
+ pydirectinput.moveTo(x, y)
33
+
34
+ def click(self, x=-1, y=-1):
35
+ super().click(x, y)
36
+ if not self.capture.clickable():
37
+ logger.info(f"window in background, not clickable")
38
+ return
39
+ # Convert the x, y position to lParam
40
+ # lParam = win32api.MAKELONG(x, y)
41
+ if x != -1 and y != -1:
42
+ x, y = self.capture.get_abs_cords(x, y)
43
+ logger.info(f"left_click {x, y}")
44
+ pydirectinput.moveTo(x, y)
45
+ pydirectinput.click()
46
+
47
+ def should_capture(self):
48
+ return self.capture.clickable()
49
+
50
+
51
+ def is_admin():
52
+ try:
53
+ # Only Windows users with admin privileges can read the C drive directly
54
+ return ctypes.windll.shell32.IsUserAnAdmin()
55
+ except:
56
+ return False
File without changes