Skip to content

Commit cf3b03d

Browse files
committed
Update dev version
Update dev version * Add GUI * Add GUI multi language
1 parent 0918771 commit cf3b03d

File tree

13 files changed

+328
-51
lines changed

13 files changed

+328
-51
lines changed

.idea/workspace.xml

Lines changed: 50 additions & 31 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

je_auto_control/gui/__init__.py

Whitespace-only changes.

je_auto_control/gui/language_wrapper/__init__.py

Whitespace-only changes.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
english_word_dict = {
2+
# Main
3+
"application_name": "AutoControlGUI",
4+
# Widget
5+
"interval_time": "Interval Time (s):",
6+
"cursor_x": "Cursor X Position:",
7+
"cursor_y": "Cursor Y Position:",
8+
"mouse_button": "Mouse Button:",
9+
"keyboard_button": "Keyboard Button:",
10+
"click_type": "Click Type:",
11+
"input_method": "Input Method:",
12+
"mouse_radio": "Mouse",
13+
"keyboard_radio": "Keyboard",
14+
"repeat_until_stopped_radio": "Repeat until stopped",
15+
"repeat_radio": "Repeat",
16+
"times": "Times",
17+
"start": "Start",
18+
"stop": "Stop",
19+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from je_auto_control.gui.language_wrapper.english import english_word_dict
2+
from je_auto_control.gui.language_wrapper.traditional_chinese import traditional_chinese_word_dict
3+
from je_auto_control.utils.logging.loggin_instance import autocontrol_logger
4+
5+
6+
7+
class LanguageWrapper(object):
8+
9+
def __init__(
10+
self
11+
):
12+
autocontrol_logger.info("Init LanguageWrapper")
13+
self.language: str = "English"
14+
self.choose_language_dict = {
15+
"English": english_word_dict,
16+
"Traditional_Chinese": traditional_chinese_word_dict
17+
}
18+
self.language_word_dict: dict = self.choose_language_dict.get(self.language)
19+
20+
def reset_language(self, language) -> None:
21+
autocontrol_logger.info(f"LanguageWrapper reset_language language: {language}")
22+
if language in [
23+
"English",
24+
"Traditional_Chinese"
25+
]:
26+
self.language = language
27+
self.language_word_dict = self.choose_language_dict.get(self.language)
28+
29+
30+
language_wrapper = LanguageWrapper()
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
traditional_chinese_word_dict = {
2+
# Main
3+
"application_name": "AutoControlGUI",
4+
# Widget
5+
"interval_time": "間隔時間(秒):",
6+
"cursor_x": "滑鼠游標 X 軸位置:",
7+
"cursor_y": "滑鼠游標 Y 軸位置:",
8+
"mouse_button": "滑鼠按鍵:",
9+
"keyboard_button": "鍵盤按鍵:",
10+
"click_type": "點擊類型:",
11+
"input_method": "輸入方式:",
12+
"mouse_radio": "滑鼠",
13+
"keyboard_radio": "鍵盤",
14+
"repeat_until_stopped_radio": "重複直到停止",
15+
"repeat_radio": "重複",
16+
"times": "次數",
17+
"start": "開始",
18+
"stop": "停止",
19+
}

je_auto_control/gui/main_widget.py

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
from PySide6.QtCore import QTimer
2+
from PySide6.QtGui import QIntValidator, QKeyEvent, Qt
3+
from PySide6.QtWidgets import (
4+
QWidget, QLineEdit, QComboBox, QPushButton, QVBoxLayout, QLabel,
5+
QGridLayout, QHBoxLayout, QRadioButton, QButtonGroup, QMessageBox
6+
)
7+
8+
from je_auto_control.gui.language_wrapper.multi_language_wrapper import language_wrapper
9+
from je_auto_control.utils.executor.action_executor import execute_action
10+
from je_auto_control.wrapper.auto_control_keyboard import type_keyboard
11+
from je_auto_control.wrapper.auto_control_mouse import click_mouse
12+
from je_auto_control.wrapper.auto_control_record import record, stop_record
13+
from je_auto_control.wrapper.platform_wrapper import keyboard_keys_table, mouse_keys_table
14+
15+
16+
class AutoControlGUIWidget(QWidget):
17+
18+
def __init__(self, parent=None):
19+
super().__init__(parent)
20+
21+
main_layout = QVBoxLayout()
22+
23+
# Grid for input fields
24+
grid = QGridLayout()
25+
26+
# Interval time
27+
grid.addWidget(QLabel(language_wrapper.language_word_dict.get("interval_time")), 0, 0)
28+
self.interval_input = QLineEdit()
29+
self.interval_input.setValidator(QIntValidator())
30+
grid.addWidget(self.interval_input, 0, 1)
31+
32+
# Cursor X/Y
33+
grid.addWidget(QLabel(language_wrapper.language_word_dict.get("cursor_x")), 2, 0)
34+
self.cursor_x_input = QLineEdit()
35+
self.cursor_x_input.setValidator(QIntValidator())
36+
grid.addWidget(self.cursor_x_input, 2, 1)
37+
38+
grid.addWidget(QLabel(language_wrapper.language_word_dict.get("cursor_y")), 3, 0)
39+
self.cursor_y_input = QLineEdit()
40+
self.cursor_y_input.setValidator(QIntValidator())
41+
grid.addWidget(self.cursor_y_input, 3, 1)
42+
43+
# Mouse button
44+
grid.addWidget(QLabel(language_wrapper.language_word_dict.get("mouse_button")), 4, 0)
45+
self.mouse_button_combo = QComboBox()
46+
self.mouse_button_combo.addItems(mouse_keys_table)
47+
grid.addWidget(self.mouse_button_combo, 4, 1)
48+
49+
# Keyboard button
50+
grid.addWidget(QLabel(language_wrapper.language_word_dict.get("keyboard_button")), 5, 0)
51+
self.keyboard_button_combo = QComboBox()
52+
self.keyboard_button_combo.addItems(keyboard_keys_table.keys())
53+
grid.addWidget(self.keyboard_button_combo, 5, 1)
54+
55+
# Click type
56+
grid.addWidget(QLabel(language_wrapper.language_word_dict.get("click_type")), 6, 0)
57+
self.click_type_combo = QComboBox()
58+
self.click_type_combo.addItems(["Single Click", "Double Click"])
59+
grid.addWidget(self.click_type_combo, 6, 1)
60+
61+
# Input method selection
62+
grid.addWidget(QLabel(language_wrapper.language_word_dict.get("input_method")), 7, 0)
63+
self.mouse_radio = QRadioButton(language_wrapper.language_word_dict.get("mouse_radio"))
64+
self.keyboard_radio = QRadioButton(language_wrapper.language_word_dict.get("keyboard_radio"))
65+
self.mouse_radio.setChecked(True)
66+
self.input_method_group = QButtonGroup()
67+
self.input_method_group.addButton(self.mouse_radio)
68+
self.input_method_group.addButton(self.keyboard_radio)
69+
grid.addWidget(self.mouse_radio, 7, 1)
70+
grid.addWidget(self.keyboard_radio, 7, 2)
71+
72+
main_layout.addLayout(grid)
73+
74+
# Repeat options
75+
repeat_layout = QHBoxLayout()
76+
self.repeat_until_stopped = QRadioButton(language_wrapper.language_word_dict.get("repeat_until_stopped_radio"))
77+
self.repeat_count_times = QRadioButton(language_wrapper.language_word_dict.get("repeat_radio"))
78+
self.repeat_count_input = QLineEdit()
79+
self.repeat_count_input.setValidator(QIntValidator())
80+
self.repeat_count_input.setPlaceholderText(language_wrapper.language_word_dict.get("times"))
81+
repeat_group = QButtonGroup()
82+
repeat_group.addButton(self.repeat_until_stopped)
83+
repeat_group.addButton(self.repeat_count_times)
84+
self.repeat_until_stopped.setChecked(True)
85+
self.repeat_count = 0
86+
self.repeat_max = 0
87+
88+
repeat_layout.addWidget(self.repeat_until_stopped)
89+
repeat_layout.addWidget(self.repeat_count_times)
90+
repeat_layout.addWidget(self.repeat_count_input)
91+
main_layout.addLayout(repeat_layout)
92+
93+
# Start/Stop buttons
94+
button_layout = QHBoxLayout()
95+
self.start_button = QPushButton(language_wrapper.language_word_dict.get("start"))
96+
self.start_button.clicked.connect(self.start_autocontrol)
97+
self.stop_button = QPushButton(language_wrapper.language_word_dict.get("stop"))
98+
self.stop_button.clicked.connect(self.stop_autocontrol)
99+
button_layout.addWidget(self.start_button)
100+
button_layout.addWidget(self.stop_button)
101+
main_layout.addLayout(button_layout)
102+
103+
# Timer
104+
self.start_autocontrol_timer = QTimer()
105+
106+
# Connect input method toggle
107+
self.mouse_radio.toggled.connect(self.update_input_mode)
108+
self.keyboard_radio.toggled.connect(self.update_input_mode)
109+
self.update_input_mode()
110+
111+
self.setLayout(main_layout)
112+
113+
def update_input_mode(self):
114+
use_mouse = self.mouse_radio.isChecked()
115+
self.cursor_x_input.setEnabled(use_mouse)
116+
self.cursor_y_input.setEnabled(use_mouse)
117+
self.mouse_button_combo.setEnabled(use_mouse)
118+
self.keyboard_button_combo.setEnabled(not use_mouse)
119+
120+
def start_autocontrol(self):
121+
self.start_autocontrol_timer.setInterval(int(self.interval_input.text()))
122+
self.start_autocontrol_timer.timeout.connect(lambda: self.start_timer_function())
123+
self.start_autocontrol_timer.start()
124+
self.repeat_max = int(self.repeat_count_input.text())
125+
126+
def start_timer_function(self):
127+
if self.repeat_until_stopped.isChecked():
128+
self.trigger_autocontrol_function()
129+
elif self.repeat_count_times.isChecked():
130+
self.repeat_count += 1
131+
if self.repeat_count < self.repeat_max:
132+
self.trigger_autocontrol_function()
133+
else:
134+
self.repeat_count = 0
135+
self.repeat_max = 0
136+
self.start_autocontrol_timer.stop()
137+
138+
def trigger_autocontrol_function(self):
139+
click_type = self.click_type_combo.currentText()
140+
if self.mouse_radio.isChecked():
141+
trigger_function = click_mouse
142+
button = self.mouse_button_combo.currentText()
143+
x = int(self.cursor_x_input.text())
144+
y = int(self.cursor_y_input.text())
145+
if click_type == "Single Click":
146+
trigger_function(mouse_keycode=button, x=x, y=y)
147+
elif click_type == "Double Click":
148+
trigger_function(mouse_keycode=button, x=x, y=y)
149+
trigger_function(mouse_keycode=button, x=x, y=y)
150+
elif self.keyboard_radio.isChecked():
151+
trigger_function = type_keyboard
152+
button = self.keyboard_button_combo.currentText()
153+
if click_type == "Single Click":
154+
trigger_function(keycode=button)
155+
elif click_type == "Double Click":
156+
trigger_function(keycode=button)
157+
trigger_function(keycode=button)
158+
159+
def stop_autocontrol(self):
160+
self.start_autocontrol_timer.stop()
161+
162+
163+
def keyPressEvent(self, event: QKeyEvent):
164+
if event.modifiers() == Qt.KeyboardModifier.ControlModifier and event.key() == Qt.Key.Key_4:
165+
self.start_autocontrol_timer.stop()
166+
else:
167+
super().keyPressEvent(event)

je_auto_control/gui/main_window.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import sys
2+
3+
from PySide6.QtWidgets import QMainWindow, QApplication
4+
from qt_material import QtStyleTools
5+
6+
from je_auto_control.gui.language_wrapper.multi_language_wrapper import language_wrapper
7+
from je_auto_control.gui.main_widget import AutoControlGUIWidget
8+
9+
10+
class AutoControlGUIUI(QMainWindow, QtStyleTools):
11+
12+
def __init__(self):
13+
super().__init__()
14+
self.id = language_wrapper.language_word_dict.get("application_name")
15+
if sys.platform in ["win32", "cygwin", "msys"]:
16+
from ctypes import windll
17+
windll.shell32.SetCurrentProcessExplicitAppUserModelID(self.id)
18+
self.setStyleSheet(
19+
f"font-size: 12pt;"
20+
f"font-family: 'Lato';"
21+
)
22+
self.apply_stylesheet(self, "dark_amber.xml")
23+
self.auto_control_gui_widget = AutoControlGUIWidget()
24+
self.setCentralWidget(self.auto_control_gui_widget)

je_auto_control/wrapper/auto_control_keyboard.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import sys
2-
from typing import Tuple
2+
from typing import Tuple, Union, LiteralString, Any
33

44
from je_auto_control.utils.exception.exception_tags import keyboard_hotkey
55
from je_auto_control.utils.exception.exception_tags import keyboard_press_key
@@ -25,7 +25,7 @@ def get_keyboard_keys_table() -> dict:
2525
return keyboard_keys_table
2626

2727

28-
def press_keyboard_key(keycode: [int, str], is_shift: bool = False, skip_record: bool = False) -> str:
28+
def press_keyboard_key(keycode: Union[int, str], is_shift: bool = False, skip_record: bool = False) -> str | None:
2929
"""
3030
use to press a key still press to use release key
3131
or use critical exit
@@ -81,7 +81,7 @@ def press_keyboard_key(keycode: [int, str], is_shift: bool = False, skip_record:
8181
)
8282

8383

84-
def release_keyboard_key(keycode: [int, str], is_shift: bool = False, skip_record: bool = False) -> str:
84+
def release_keyboard_key(keycode: Union[int, str], is_shift: bool = False, skip_record: bool = False) -> str | None:
8585
"""
8686
use to release pressed key return keycode
8787
:param keycode which keycode we want to release
@@ -103,11 +103,11 @@ def release_keyboard_key(keycode: [int, str], is_shift: bool = False, skip_recor
103103
keyboard.release_key(keycode)
104104
elif sys.platform in ["darwin"]:
105105
keyboard.release_key(keycode, is_shift=is_shift)
106-
if skip_record is False:
106+
if not skip_record:
107107
record_action_to_list("release_key", param)
108108
return str(keycode)
109109
except AutoControlKeyboardException as error:
110-
if skip_record is False:
110+
if not skip_record:
111111
record_action_to_list("release_key", param, repr(error))
112112
autocontrol_logger.error(
113113
f"release_keyboard_key, keycode: {keycode}, is_shift: {is_shift}, skip_record: {skip_record}, "
@@ -131,7 +131,7 @@ def release_keyboard_key(keycode: [int, str], is_shift: bool = False, skip_recor
131131
)
132132

133133

134-
def type_keyboard(keycode: [int, str], is_shift: bool = False, skip_record: bool = False) -> str:
134+
def type_keyboard(keycode: Union[int, str], is_shift: bool = False, skip_record: bool = False) -> str | None:
135135
"""
136136
press and release key return keycode
137137
:param keycode which keycode we want to type
@@ -146,35 +146,35 @@ def type_keyboard(keycode: [int, str], is_shift: bool = False, skip_record: bool
146146
try:
147147
press_keyboard_key(keycode, is_shift, skip_record=True)
148148
release_keyboard_key(keycode, is_shift, skip_record=True)
149-
if skip_record is False:
149+
if not skip_record:
150150
record_action_to_list("type_keyboard", param)
151151
return str(keycode)
152152
except AutoControlKeyboardException as error:
153-
if skip_record is False:
153+
if not skip_record:
154154
record_action_to_list("type_keyboard", param, repr(error))
155155
autocontrol_logger.error(
156156
f"type_keyboard, keycode: {keycode}, is_shift: {is_shift}, skip_record: {skip_record}, "
157157
f"failed: {repr(AutoControlKeyboardException(keyboard_type_key + ' ' + repr(error)))}"
158158
)
159159
raise AutoControlKeyboardException(keyboard_type_key + " " + repr(error))
160160
except TypeError as error:
161-
if skip_record is False:
161+
if not skip_record:
162162
record_action_to_list("type_keyboard", param, repr(error))
163163
autocontrol_logger.error(
164164
f"type_keyboard, keycode: {keycode}, is_shift: {is_shift}, skip_record: {skip_record}, "
165165
f"failed: {repr(AutoControlKeyboardException(repr(error)))}"
166166
)
167167
raise AutoControlKeyboardException(repr(error))
168168
except Exception as error:
169-
if skip_record is False:
169+
if not skip_record:
170170
record_action_to_list("type_keyboard", param, repr(error))
171171
autocontrol_logger.error(
172172
f"type_keyboard, keycode: {keycode}, is_shift: {is_shift}, skip_record: {skip_record}, "
173173
f"failed: {repr(error)}"
174174
)
175175

176176

177-
def check_key_is_press(keycode: [int, str]) -> bool:
177+
def check_key_is_press(keycode: [int, str]) -> bool | None:
178178
"""
179179
use to check key is press return True or False
180180
:param keycode check key is press or not
@@ -198,7 +198,7 @@ def check_key_is_press(keycode: [int, str]) -> bool:
198198
)
199199

200200

201-
def write(write_string: str, is_shift: bool = False) -> str:
201+
def write(write_string: str, is_shift: bool = False) -> None | LiteralString | str:
202202
"""
203203
use to press and release whole we get this function str
204204
return all press and release str
@@ -257,7 +257,7 @@ def write(write_string: str, is_shift: bool = False) -> str:
257257
)
258258

259259

260-
def hotkey(key_code_list: list, is_shift: bool = False) -> Tuple[str, str]:
260+
def hotkey(key_code_list: list, is_shift: bool = False) -> tuple[str, str] | None:
261261
"""
262262
use to press and release all key on key_code_list
263263
then reverse list press and release again

je_auto_control/wrapper/auto_control_mouse.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def get_mouse_table() -> dict:
2424
return mouse_keys_table
2525

2626

27-
def mouse_preprocess(mouse_keycode: [int, str], x: int, y: int) -> Tuple[Union[int, str], int, int]:
27+
def mouse_preprocess(mouse_keycode: Union[int, str], x: int, y: int) -> Tuple[Union[int, str], int, int]:
2828
"""
2929
check mouse keycode is verified or not
3030
and then check current mouse position
@@ -168,7 +168,7 @@ def release_mouse(mouse_keycode: [int, str], x: int = None, y: int = None) -> Tu
168168
)
169169

170170

171-
def click_mouse(mouse_keycode: [int, str], x: int = None, y: int = None) -> Tuple[Union[int, str], int, int]:
171+
def click_mouse(mouse_keycode: Union[int, str], x: int = None, y: int = None) -> Tuple[Union[int, str], int, int]:
172172
"""
173173
press and release mouse keycode on x, y
174174
return keycode, x, y

0 commit comments

Comments
 (0)