From 9b1f0fc78448e7af415dc26f0119d92709678053 Mon Sep 17 00:00:00 2001 From: Mekotofeuka Date: Wed, 18 Mar 2026 22:45:39 +0900 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=5Fedit=5Fconfig=5Fdialog=20=D1=81=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=87=D0=B8=D0=BC=20=D0=BA=D0=BE=D0=BD=D1=82=D0=B5?= =?UTF-8?q?=D0=BA=D1=81=D1=82=D0=BD=D1=8B=D0=BC=20=D0=BC=D0=B5=D0=BD=D1=8E?= =?UTF-8?q?=20=D0=B8=20Ctrl+C/V=20=D1=81=D0=BA=D0=BE=D0=BF=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D1=82=D1=8C/=D0=B2=D1=81=D1=82=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C/=D0=B2=D1=8B=D1=80=D0=B5=D0=B7=D0=B0=D1=82?= =?UTF-8?q?=D1=8C/=D0=B2=D1=8B=D0=B4=D0=B5=D0=BB=D0=B8=D1=82=D1=8C=20?= =?UTF-8?q?=D0=B2=D1=81=D1=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- windows.py | 101 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 83 insertions(+), 18 deletions(-) diff --git a/windows.py b/windows.py index 8e8ed5d..03deead 100644 --- a/windows.py +++ b/windows.py @@ -335,7 +335,9 @@ def _edit_config_dialog(): frame = ctk.CTkFrame(root, fg_color=BG, corner_radius=0) frame.pack(fill="both", expand=True, padx=24, pady=20) - # Host + # --- Поля ввода --- + + # IP прокси ctk.CTkLabel(frame, text="IP-адрес прокси", font=(FONT_FAMILY, 13), text_color=TEXT_PRIMARY, anchor="w").pack(anchor="w", pady=(0, 4)) @@ -346,7 +348,7 @@ def _edit_config_dialog(): border_width=1, text_color=TEXT_PRIMARY) host_entry.pack(anchor="w", pady=(0, 12)) - # Port + # Порт прокси ctk.CTkLabel(frame, text="Порт прокси", font=(FONT_FAMILY, 13), text_color=TEXT_PRIMARY, anchor="w").pack(anchor="w", pady=(0, 4)) @@ -357,7 +359,7 @@ def _edit_config_dialog(): border_width=1, text_color=TEXT_PRIMARY) port_entry.pack(anchor="w", pady=(0, 12)) - # DC-IP mappings + # DC → IP маппинги ctk.CTkLabel(frame, text="DC → IP маппинги (по одному на строку, формат DC:IP)", font=(FONT_FAMILY, 13), text_color=TEXT_PRIMARY, anchor="w").pack(anchor="w", pady=(0, 4)) @@ -368,7 +370,76 @@ def _edit_config_dialog(): dc_textbox.pack(anchor="w", pady=(0, 12)) dc_textbox.insert("1.0", "\n".join(cfg.get("dc_ip", DEFAULT_CONFIG["dc_ip"]))) - # Verbose + # --- Контекстное меню и Ctrl shortcuts --- + def make_editable(widget, is_textbox=False): + import tkinter as tk + + menu = tk.Menu(widget, tearoff=0) + + def cut(): + try: + if is_textbox: + text = widget.get("sel.first", "sel.last") + widget.delete("sel.first", "sel.last") + else: + text = widget.get()[widget.index("sel.first"):widget.index("sel.last")] + widget.delete("sel.first", "sel.last") + widget.clipboard_clear() + widget.clipboard_append(text) + except Exception: + pass + + def copy(): + try: + if is_textbox: + text = widget.get("sel.first", "sel.last") + else: + text = widget.get()[widget.index("sel.first"):widget.index("sel.last")] + widget.clipboard_clear() + widget.clipboard_append(text) + except Exception: + pass + + def paste(): + try: + text = widget.clipboard_get() + if is_textbox: + widget.insert("insert", text) + else: + widget.insert(widget.index("insert"), text) + except Exception: + pass + + def select_all(event=None): + if is_textbox: + widget.tag_add("sel", "1.0", "end") + else: + widget.selection_range(0, "end") + return "break" + + menu.add_command(label="Вырезать", command=cut) + menu.add_command(label="Копировать", command=copy) + menu.add_command(label="Вставить", command=paste) + menu.add_command(label="Выделить всё", command=select_all) + + def show_menu(event): + menu.tk_popup(event.x_root, event.y_root) + + widget.bind("", show_menu) + widget.bind("", select_all) + widget.bind("", select_all) + widget.bind("", lambda e: copy()) + widget.bind("", lambda e: copy()) + widget.bind("", lambda e: cut()) + widget.bind("", lambda e: cut()) + widget.bind("", lambda e: paste()) + widget.bind("", lambda e: paste()) + + make_editable(host_entry) + make_editable(port_entry) + make_editable(dc_textbox, is_textbox=True) + + # --- Verbose --- verbose_var = ctk.BooleanVar(value=cfg.get("verbose", False)) ctk.CTkCheckBox(frame, text="Подробное логирование (verbose)", variable=verbose_var, font=(FONT_FAMILY, 13), @@ -382,6 +453,7 @@ def _edit_config_dialog(): font=(FONT_FAMILY, 11), text_color=TEXT_SECONDARY, anchor="w").pack(anchor="w", pady=(0, 16)) + # --- Кнопки Сохранить / Отмена --- def on_save(): import socket as _sock host_val = host_var.get().strip() @@ -393,14 +465,13 @@ def _edit_config_dialog(): try: port_val = int(port_var.get().strip()) - if not (1 <= port_val <= 65535): + if not (0 <= port_val <= 65535): raise ValueError except ValueError: - _show_error("Порт должен быть числом 1-65535") + _show_error("Порт должен быть числом 0-65535") return - lines = [l.strip() for l in dc_textbox.get("1.0", "end").strip().splitlines() - if l.strip()] + lines = [l.strip() for l in dc_textbox.get("1.0", "end").strip().splitlines() if l.strip()] try: tg_ws_proxy.parse_dc_ip_list(lines) except ValueError as e: @@ -420,10 +491,7 @@ def _edit_config_dialog(): _tray_icon.menu = _build_menu() from tkinter import messagebox - if messagebox.askyesno("Перезапустить?", - "Настройки сохранены.\n\n" - "Перезапустить прокси сейчас?", - parent=root): + if messagebox.askyesno("Перезапустить?", "Настройки сохранены.\n\nПерезапустить прокси сейчас?", parent=root): root.destroy() restart_proxy() else: @@ -437,18 +505,15 @@ def _edit_config_dialog(): ctk.CTkButton(btn_frame, text="Сохранить", width=140, height=38, font=(FONT_FAMILY, 14, "bold"), corner_radius=10, fg_color=TG_BLUE, hover_color=TG_BLUE_HOVER, - text_color="#ffffff", - command=on_save).pack(side="left", padx=(0, 10)) + text_color="#ffffff", command=on_save).pack(side="left", padx=(0, 10)) ctk.CTkButton(btn_frame, text="Отмена", width=140, height=38, font=(FONT_FAMILY, 14), corner_radius=10, fg_color=FIELD_BG, hover_color=FIELD_BORDER, - text_color=TEXT_PRIMARY, border_width=1, - border_color=FIELD_BORDER, + text_color=TEXT_PRIMARY, border_width=1, border_color=FIELD_BORDER, command=on_cancel).pack(side="left") root.mainloop() - def _on_open_logs(icon=None, item=None): log.info("Opening log file: %s", LOG_FILE) if LOG_FILE.exists(): @@ -702,4 +767,4 @@ def main(): if __name__ == "__main__": - main() + main() \ No newline at end of file