From 1b8ec26f984a41bc356e843cfdb0f83982fb0e62 Mon Sep 17 00:00:00 2001 From: JE-Chen <33644111+JE-Chen@users.noreply.github.com> Date: Tue, 2 Sep 2025 03:16:42 +0800 Subject: [PATCH 1/7] Update dev version Update dependency version --- .idea/workspace.xml | 83 +++++++++++++++++++++++---------------------- pyproject.toml | 4 +-- stable.toml | 2 +- 3 files changed, 46 insertions(+), 43 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 92fe69f..05e4efb 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,8 +5,6 @@ - - - { - "keyToString": { - "DefaultHtmlFileTemplate": "HTML File", - "Python.calculator.executor": "Run", - "Python.callback_test.executor": "Run", - "Python.create_project_test.executor": "Run", - "Python.critical_exit_test.executor": "Run", - "Python.executor_one_file.executor": "Run", - "Python.main_widget.executor": "Run", - "Python.main_window.executor": "Run", - "Python.record_test.executor": "Run", - "Python.screen_test.executor": "Run", - "Python.screenshot_test.executor": "Run", - "Python.video_recording.executor": "Run", - "RunOnceActivity.OpenProjectViewOnStart": "true", - "RunOnceActivity.ShowReadmeOnStart": "true", - "RunOnceActivity.git.unshallow": "true", - "WebServerToolWindowFactoryState": "false", - "git-widget-placeholder": "dev", - "ignore.virus.scanning.warn.message": "true", - "junie.onboarding.icon.badge.shown": "true", - "last_opened_file_path": "C:/CodeWorkspace/Python/AutoControlGUI", - "node.js.detected.package.eslint": "true", - "node.js.detected.package.tslint": "true", - "node.js.selected.package.eslint": "(autodetect)", - "node.js.selected.package.tslint": "(autodetect)", - "nodejs_package_manager_path": "npm", - "settings.editor.selected.configurable": "com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable", - "vue.rearranger.settings.migration": "true" + +}]]> @@ -121,7 +120,7 @@ - + - + + - - @@ -588,6 +587,9 @@ + + + @@ -610,13 +612,14 @@ - + + diff --git a/pyproject.toml b/pyproject.toml index 13e70d7..0df117d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta" [project] name = "je_auto_control_dev" -version = "0.0.117" +version = "0.0.118" authors = [ { name = "JE-Chen", email = "jechenmailman@gmail.com" }, ] @@ -43,4 +43,4 @@ content-type = "text/markdown" find = { namespaces = false } [project.optional-dependencies] -gui = ["PySide6==6.9.1", "qt-material"] +gui = ["PySide6==6.9.2", "qt-material"] diff --git a/stable.toml b/stable.toml index 0142098..44f479a 100644 --- a/stable.toml +++ b/stable.toml @@ -43,4 +43,4 @@ content-type = "text/markdown" find = { namespaces = false } [project.optional-dependencies] -gui = ["PySide6==6.9.1", "qt-material"] +gui = ["PySide6==6.9.2", "qt-material"] From 9b083838f07bd3c28d54e7718c9e667dceafa51b Mon Sep 17 00:00:00 2001 From: JE-Chen <33644111+JE-Chen@users.noreply.github.com> Date: Tue, 23 Sep 2025 09:06:39 +0800 Subject: [PATCH 2/7] Update dev version Update dev version * Add sent event to background window * Add windows window manage --- .idea/workspace.xml | 11 +++--- je_auto_control/__init__.py | 6 ++- .../keyboard/x11_linux_keyboard_control.py | 19 +++++++++- .../mouse/x11_linux_mouse_control.py | 22 ++++++++++- je_auto_control/osx/pid/__init__.py | 0 je_auto_control/osx/pid/pid_control.py | 38 +++++++++++++++++++ .../keyboard/win32_ctype_keyboard_control.py | 9 ++++- .../windows/message/window_message.py | 2 +- .../mouse/win32_ctype_mouse_control.py | 12 ++++-- ...indow_hwnd.py => windows_window_manage.py} | 9 +++++ .../wrapper/auto_control_keyboard.py | 25 +++++++++++- je_auto_control/wrapper/auto_control_mouse.py | 22 +++++++++++ pyproject.toml | 2 +- test/manual_test/windows_window.py | 2 +- 14 files changed, 163 insertions(+), 16 deletions(-) create mode 100644 je_auto_control/osx/pid/__init__.py create mode 100644 je_auto_control/osx/pid/pid_control.py rename je_auto_control/windows/window/{window_hwnd.py => windows_window_manage.py} (82%) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 05e4efb..409d375 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -4,9 +4,7 @@ - - - + @@ -249,8 +249,8 @@ - @@ -590,6 +590,7 @@ + diff --git a/je_auto_control/__init__.py b/je_auto_control/__init__.py index 34b2d2b..df8515b 100644 --- a/je_auto_control/__init__.py +++ b/je_auto_control/__init__.py @@ -87,6 +87,7 @@ from je_auto_control.wrapper.auto_control_keyboard import release_keyboard_key from je_auto_control.wrapper.auto_control_keyboard import type_keyboard from je_auto_control.wrapper.auto_control_keyboard import write +from je_auto_control.wrapper.auto_control_keyboard import send_key_event_to_window # import mouse from je_auto_control.wrapper.auto_control_mouse import click_mouse from je_auto_control.wrapper.auto_control_mouse import get_mouse_position @@ -96,6 +97,7 @@ from je_auto_control.wrapper.auto_control_mouse import release_mouse from je_auto_control.wrapper.auto_control_mouse import set_mouse_position from je_auto_control.wrapper.auto_control_mouse import special_mouse_keys_table +from je_auto_control.wrapper.auto_control_mouse import send_mouse_event_to_window # test_record from je_auto_control.wrapper.auto_control_record import record from je_auto_control.wrapper.auto_control_record import stop_record @@ -104,6 +106,8 @@ from je_auto_control.wrapper.auto_control_screen import screenshot # Recording from je_auto_control.utils.cv2_utils.video_recording import RecordingThread +# Windows +from je_auto_control.windows.window import windows_window_manage __all__ = [ "click_mouse", "mouse_keys_table", "get_mouse_position", "press_mouse", "release_mouse", @@ -120,5 +124,5 @@ "generate_html", "generate_html_report", "generate_json", "generate_json_report", "generate_xml", "generate_xml_report", "get_dir_files_as_list", "create_project_dir", "start_autocontrol_socket_server", "callback_executor", "package_manager", "get_special_table", "ShellManager", "default_shell_manager", - "RecordingThread" + "RecordingThread", "send_key_event_to_window", "send_mouse_event_to_window", "windows_window_manage" ] diff --git a/je_auto_control/linux_with_x11/keyboard/x11_linux_keyboard_control.py b/je_auto_control/linux_with_x11/keyboard/x11_linux_keyboard_control.py index c6524bf..fb2d4ae 100644 --- a/je_auto_control/linux_with_x11/keyboard/x11_linux_keyboard_control.py +++ b/je_auto_control/linux_with_x11/keyboard/x11_linux_keyboard_control.py @@ -9,7 +9,7 @@ from je_auto_control.linux_with_x11.core.utils.x11_linux_display import display from Xlib.ext.xtest import fake_input -from Xlib import X +from Xlib import X, protocol def press_key(keycode: int) -> None: @@ -28,3 +28,20 @@ def release_key(keycode: int) -> None: time.sleep(0.01) fake_input(display, X.KeyRelease, keycode) display.sync() + +def send_key_event_to_window(window_id, keycode: int): + window = display.create_resource_object('window', window_id) + event = protocol.event.KeyPress( + time=X.CurrentTime, + root=display.screen().root, + window=window, + same_screen=1, + child=X.NONE, + root_x=0, root_y=0, event_x=0, event_y=0, + state=0, + detail=keycode + ) + window.send_event(event, propagate=True) + event.type = X.KeyRelease + window.send_event(event, propagate=True) + display.flush() \ No newline at end of file diff --git a/je_auto_control/linux_with_x11/mouse/x11_linux_mouse_control.py b/je_auto_control/linux_with_x11/mouse/x11_linux_mouse_control.py index 9320b7d..0cd9f6e 100644 --- a/je_auto_control/linux_with_x11/mouse/x11_linux_mouse_control.py +++ b/je_auto_control/linux_with_x11/mouse/x11_linux_mouse_control.py @@ -8,7 +8,7 @@ if sys.platform not in ["linux", "linux2"]: raise AutoControlException(linux_import_error) -from Xlib import X +from Xlib import X, protocol from Xlib.ext.xtest import fake_input from je_auto_control.linux_with_x11.core.utils.x11_linux_display import display @@ -83,3 +83,23 @@ def scroll(scroll_value: int, scroll_direction: int) -> None: for i in range(scroll_value): click_mouse(scroll_direction) total = total + i + +def send_mouse_event_to_window(window_id, mouse_keycode: int, x: int = None, y: int = None): + window = display.create_resource_object('window', window_id) + for ev_type in (X.ButtonPress, X.ButtonRelease): + ev = protocol.event.ButtonPress( + time=X.CurrentTime, + root=display.screen().root, + window=window, + same_screen=1, + child=X.NONE, + root_x=x, root_y=y, event_x=x, event_y=y, + state=0, + detail=mouse_keycode + ) + ev.type = ev_type + window.send_event(ev, propagate=True) + display.flush() + + + diff --git a/je_auto_control/osx/pid/__init__.py b/je_auto_control/osx/pid/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/je_auto_control/osx/pid/pid_control.py b/je_auto_control/osx/pid/pid_control.py new file mode 100644 index 0000000..1a07ccb --- /dev/null +++ b/je_auto_control/osx/pid/pid_control.py @@ -0,0 +1,38 @@ +import objc +from Quartz import CGEventCreateKeyboardEvent, kCGEventKeyDown, kCGEventKeyUp +from ApplicationServices import ProcessSerialNumber, GetProcessForPID +from ctypes import cdll, c_void_p +import subprocess + +carbon = cdll.LoadLibrary('/System/Library/Frameworks/Carbon.framework/Carbon') + + +def send_key_to_pid(pid, keycode): + psn = ProcessSerialNumber() + GetProcessForPID(pid, objc.byref(psn)) + event_down = CGEventCreateKeyboardEvent(None, keycode, True) + event_up = CGEventCreateKeyboardEvent(None, keycode, False) + carbon.CGEventPostToPSN(c_void_p(id(psn)), event_down) + carbon.CGEventPostToPSN(c_void_p(id(psn)), event_up) + +def get_pid_by_window_title(title: str): + script = f''' + set targetWindowName to "{title}" + tell application "System Events" + repeat with proc in processes + repeat with win in windows of proc + if name of win contains targetWindowName then + return unix id of proc + end if + end repeat + end repeat + end tell + ''' + try: + pid_str = subprocess.check_output( + ["osascript", "-e", script], + stderr=subprocess.DEVNULL + ).decode().strip() + return int(pid_str) if pid_str else None + except subprocess.CalledProcessError: + return None diff --git a/je_auto_control/windows/keyboard/win32_ctype_keyboard_control.py b/je_auto_control/windows/keyboard/win32_ctype_keyboard_control.py index 1f833a3..4feb57f 100644 --- a/je_auto_control/windows/keyboard/win32_ctype_keyboard_control.py +++ b/je_auto_control/windows/keyboard/win32_ctype_keyboard_control.py @@ -6,7 +6,7 @@ if sys.platform not in ["win32", "cygwin", "msys"]: raise AutoControlException(windows_import_error) -from je_auto_control.windows.core.utils.win32_ctype_input import Input +from je_auto_control.windows.core.utils.win32_ctype_input import Input, user32 from je_auto_control.windows.core.utils.win32_ctype_input import Keyboard from je_auto_control.windows.core.utils.win32_ctype_input import KeyboardInput from je_auto_control.windows.core.utils.win32_ctype_input import SendInput @@ -28,3 +28,10 @@ def release_key(keycode: int) -> None: """ keyboard = Input(type=Keyboard, ki=KeyboardInput(wVk=keycode, dwFlags=win32_EventF_KEYUP)) SendInput(1, ctypes.byref(keyboard), ctypes.sizeof(keyboard)) + +def send_key_event_to_window(window: str, keycode: int): + WM_KEYDOWN = 0x0100 + WM_KEYUP = 0x0101 + window = user32.FindWindowW(None, window) + user32.PostMessageW(window, WM_KEYDOWN, keycode, 0) + user32.PostMessageW(window, WM_KEYUP, keycode, 0) diff --git a/je_auto_control/windows/message/window_message.py b/je_auto_control/windows/message/window_message.py index cfbf533..526d569 100644 --- a/je_auto_control/windows/message/window_message.py +++ b/je_auto_control/windows/message/window_message.py @@ -1,5 +1,5 @@ from je_auto_control.windows.core.utils.win32_ctype_input import user32 -from je_auto_control.windows.window.window_hwnd import FindWindowW +from je_auto_control.windows.window.windows_window_manage import FindWindowW PostMessageW = user32.PostMessageW SendMessageW = user32.SendMessageW diff --git a/je_auto_control/windows/mouse/win32_ctype_mouse_control.py b/je_auto_control/windows/mouse/win32_ctype_mouse_control.py index 89a0ef4..bda2873 100644 --- a/je_auto_control/windows/mouse/win32_ctype_mouse_control.py +++ b/je_auto_control/windows/mouse/win32_ctype_mouse_control.py @@ -7,7 +7,7 @@ if sys.platform not in ["win32", "cygwin", "msys"]: raise AutoControlException(windows_import_error) -from je_auto_control.windows.core.utils.win32_ctype_input import Input +from je_auto_control.windows.core.utils.win32_ctype_input import Input, user32 from je_auto_control.windows.core.utils.win32_vk import win32_LEFTDOWN from je_auto_control.windows.core.utils.win32_vk import win32_LEFTUP from je_auto_control.windows.core.utils.win32_vk import win32_MIDDLEDOWN @@ -50,7 +50,7 @@ def mouse_event(event, x: int, y: int, dwData: int = 0) -> None: ctypes.windll.user32.mouse_event(event, ctypes.c_long(converted_x), ctypes.c_long(converted_y), dwData, 0) -def position() -> [Tuple[int, int], None]: +def position() -> tuple[int, int] | None: """ get mouse position """ @@ -102,10 +102,16 @@ def click_mouse(mouse_keycode: int, x: int = None, y: int = None) -> None: release_mouse(mouse_keycode) -def scroll(scroll_value: int, x: int = None, y: int = None) -> None: +def scroll(scroll_value: int, x: int = None, y: int = None) -> None: """ :param scroll_value scroll count :param x scroll x :param y scroll y """ mouse_event(win32_WHEEL, x, y, dwData=scroll_value) + + +def send_mouse_event_to_window(window, mouse_keycode: int, x: int = None, y: int = None): + lparam = (y << 16) | x + user32.PostMessageW(window, mouse_keycode, 1, lparam) + user32.PostMessageW(window, mouse_keycode, 0, lparam) diff --git a/je_auto_control/windows/window/window_hwnd.py b/je_auto_control/windows/window/windows_window_manage.py similarity index 82% rename from je_auto_control/windows/window/window_hwnd.py rename to je_auto_control/windows/window/windows_window_manage.py index 1b7ae08..96815ce 100644 --- a/je_auto_control/windows/window/window_hwnd.py +++ b/je_auto_control/windows/window/windows_window_manage.py @@ -38,3 +38,12 @@ def close_window(hwnd) -> bool: def destroy_window(hwnd) -> bool: return DestroyWindow(hwnd) + + +def set_foreground_window(hwnd) -> None: + user32.SetForegroundWindow(hwnd) + +def set_window_positon(hwnd, position: int) -> None: + swp_no_size = 0x0001 + swp_no_move = 0x0002 + user32.SetWindowPos(hwnd, position, 0, 0, 0, 0, swp_no_move | swp_no_size) \ No newline at end of file diff --git a/je_auto_control/wrapper/auto_control_keyboard.py b/je_auto_control/wrapper/auto_control_keyboard.py index 954a6ff..b508d40 100644 --- a/je_auto_control/wrapper/auto_control_keyboard.py +++ b/je_auto_control/wrapper/auto_control_keyboard.py @@ -174,7 +174,7 @@ def type_keyboard(keycode: Union[int, str], is_shift: bool = False, skip_record: ) -def check_key_is_press(keycode: [int, str]) -> bool | None: +def check_key_is_press(keycode: Union[int, str]) -> bool | None: """ use to check key is press return True or False :param keycode check key is press or not @@ -302,3 +302,26 @@ def hotkey(key_code_list: list, is_shift: bool = False) -> tuple[str, str] | Non f"hotkey, key_code_list: {key_code_list}, is_shift: {is_shift}, " f"failed: {repr(error)}" ) + +def send_key_event_to_window(window_title, keycode: int): + autocontrol_logger.info( + f"send_key_event_to_window window:{window_title}, keycode:{keycode}" + ) + param = locals() + try: + if sys.platform in ["darwin"]: + return + if isinstance(keycode, int): + get_key_code = keycode + else: + get_key_code = keyboard_keys_table.get(keycode) + keyboard.send_key_event_to_window( + window_title, + keycode=keycode + ) + except Exception as error: + record_action_to_list("send_key_event_to_window", param, repr(error)) + autocontrol_logger.error( + f"send_key_event_to_window window:{window_title}, keycode:{keycode}" + f"failed: {repr(error)}" + ) diff --git a/je_auto_control/wrapper/auto_control_mouse.py b/je_auto_control/wrapper/auto_control_mouse.py index ce9a0c7..8966d6a 100644 --- a/je_auto_control/wrapper/auto_control_mouse.py +++ b/je_auto_control/wrapper/auto_control_mouse.py @@ -263,3 +263,25 @@ def mouse_scroll( f"mouse_scroll, scroll_value: {scroll_value}, x: {x}, y: {y}, scroll_direction: {scroll_direction}, " f"failed: {repr(error)}" ) + +def send_mouse_event_to_window(window, mouse_keycode: Union[int, str], x: int = None, y: int = None): + autocontrol_logger.info( + f"send_mouse_event_to_window window:{window} mouse_keycode:{mouse_keycode}, x: {x}, y: {y}" + ) + param = locals() + try: + if sys.platform in ["darwin"]: + return + mouse_keycode, x, y = mouse_preprocess(mouse_keycode, x, y) + mouse.send_mouse_event_to_window( + window, + mouse_keycode=mouse_keycode, + x=x, + y=y, + ) + except Exception as error: + record_action_to_list("send_mouse_event_to_window", param, repr(error)) + autocontrol_logger.error( + f"send_mouse_event_to_window window:{window} mouse_keycode:{mouse_keycode}, x: {x}, y: {y}" + f"failed: {repr(error)}" + ) \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 0df117d..9d84ff4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta" [project] name = "je_auto_control_dev" -version = "0.0.118" +version = "0.0.119" authors = [ { name = "JE-Chen", email = "jechenmailman@gmail.com" }, ] diff --git a/test/manual_test/windows_window.py b/test/manual_test/windows_window.py index 49945ec..286f940 100644 --- a/test/manual_test/windows_window.py +++ b/test/manual_test/windows_window.py @@ -1,5 +1,5 @@ from je_auto_control.windows.message.window_message import post_message_to_window, messages -from je_auto_control.windows.window.window_hwnd import get_all_window_hwnd +from je_auto_control.windows.window.windows_window_manage import get_all_window_hwnd hwnd_list = get_all_window_hwnd() print(hwnd_list) From 4dfc36de8f4c77ae52f990b5e35e03029adf76d5 Mon Sep 17 00:00:00 2001 From: JE-Chen <33644111+JE-Chen@users.noreply.github.com> Date: Tue, 23 Sep 2025 09:18:40 +0800 Subject: [PATCH 3/7] Update dev version Update dev version * Update shell_exec.py ** Using readline and decode replace --- je_auto_control/utils/shell_process/shell_exec.py | 11 ++++++----- pyproject.toml | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/je_auto_control/utils/shell_process/shell_exec.py b/je_auto_control/utils/shell_process/shell_exec.py index 8044051..faf8cf8 100644 --- a/je_auto_control/utils/shell_process/shell_exec.py +++ b/je_auto_control/utils/shell_process/shell_exec.py @@ -3,6 +3,7 @@ import subprocess import sys from threading import Thread +from typing import Union from je_auto_control.utils.logging.loggin_instance import autocontrol_logger @@ -21,7 +22,7 @@ def __init__( self.read_program_error_output_from_thread = None self.read_program_output_from_thread = None self.still_run_shell: bool = True - self.process = None + self.process: Union[subprocess.Popen, None] = None self.run_output_queue: queue = queue.Queue() self.run_error_queue: queue = queue.Queue() self.program_encoding: str = shell_encoding @@ -115,16 +116,16 @@ def print_and_clear_queue(self) -> None: def read_program_output_from_process(self) -> None: while self.still_run_shell: - program_output_data = self.process.stdout.raw.read( + program_output_data = self.process.stdout.readline( self.program_buffer) \ - .decode(self.program_encoding) + .decode(self.program_encoding, "replace") self.run_output_queue.put_nowait(program_output_data) def read_program_error_output_from_process(self) -> None: while self.still_run_shell: - program_error_output_data = self.process.stderr.raw.read( + program_error_output_data = self.process.stderr.readline( self.program_buffer) \ - .decode(self.program_encoding) + .decode(self.program_encoding, "replace") self.run_error_queue.put_nowait(program_error_output_data) diff --git a/pyproject.toml b/pyproject.toml index 9d84ff4..a3364dd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta" [project] name = "je_auto_control_dev" -version = "0.0.119" +version = "0.0.120" authors = [ { name = "JE-Chen", email = "jechenmailman@gmail.com" }, ] From e3df0910108b6cd4a4005a78ca4b2edd75ae8c6b Mon Sep 17 00:00:00 2001 From: JE-Chen <33644111+JE-Chen@users.noreply.github.com> Date: Tue, 23 Sep 2025 09:40:37 +0800 Subject: [PATCH 4/7] Update stable version Update stable version --- stable.toml => dev.toml | 10 +++++----- pyproject.toml | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) rename stable.toml => dev.toml (89%) diff --git a/stable.toml b/dev.toml similarity index 89% rename from stable.toml rename to dev.toml index 44f479a..a3364dd 100644 --- a/stable.toml +++ b/dev.toml @@ -1,12 +1,12 @@ -# Rename to build stable version -# This is stable version +# Rename to build dev version +# This is dev version [build-system] -requires = ["setuptools>=61.0"] +requires = ["setuptools"] build-backend = "setuptools.build_meta" [project] -name = "je_auto_control" -version = "0.0.171" +name = "je_auto_control_dev" +version = "0.0.120" authors = [ { name = "JE-Chen", email = "jechenmailman@gmail.com" }, ] diff --git a/pyproject.toml b/pyproject.toml index a3364dd..e805857 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,12 @@ -# Rename to build dev version -# This is dev version +# Rename to build stable version +# This is stable version [build-system] -requires = ["setuptools"] +requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" [project] -name = "je_auto_control_dev" -version = "0.0.120" +name = "je_auto_control" +version = "0.0.172" authors = [ { name = "JE-Chen", email = "jechenmailman@gmail.com" }, ] From 5b448a996f2f7542a5e4cc2b05074ee6f35bcbe8 Mon Sep 17 00:00:00 2001 From: JE-Chen <33644111+JE-Chen@users.noreply.github.com> Date: Tue, 23 Sep 2025 10:11:23 +0800 Subject: [PATCH 5/7] Update dev version Update dev version * Update type hint --- .idea/workspace.xml | 61 ++++++++++--------- .../utils/shell_process/shell_exec.py | 6 +- pyproject.toml | 10 +-- dev.toml => stable.toml | 10 +-- 4 files changed, 46 insertions(+), 41 deletions(-) rename dev.toml => stable.toml (89%) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 409d375..5ab9719 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -73,6 +73,8 @@ - - + + - + - + - + + + - - - @@ -591,6 +593,7 @@ + @@ -612,21 +615,23 @@