Enhance terminal widgets with read-only mode and clear functionality

- Add read-only mode to TerminalWidget to prevent manual text editing
- Disable text paste and key input in terminal widgets
- Modify context menu to remove cut and paste options
- Add clear buttons for interactive, file execution, and TFTP log terminals
- Implement temporary state changes for text appending and clearing
This commit is contained in:
2025-02-19 21:49:49 +03:00
parent 0ebcf9cb6a
commit 7d92682482

View File

@@ -695,17 +695,33 @@ class TerminalWidget(CustomText):
pady=5,
spacing1=2, # Отступ перед абзацем
spacing2=2, # Межстрочный интервал
spacing3=2 # Отступ после абзаца
spacing3=2, # Отступ после абзаца
state='disabled' # Делаем виджет только для чтения
)
# Счетчик команд для разделителей
self.command_counter = 0
# Отключаем возможность вставки текста
self.bind('<<Paste>>', lambda e: 'break')
self.bind('<Key>', self._readonly)
# Изменяем контекстное меню
self.context_menu.delete("Вырезать")
self.context_menu.delete("Вставить")
def _readonly(self, event):
"""Обработчик для блокировки ввода"""
return 'break'
def append_text(self, text, message_type=None):
"""
Добавление текста с определенным типом сообщения
message_type может быть: 'error', 'warning', 'info', 'command'
"""
# Временно разрешаем изменение для добавления текста
self.config(state='normal')
# Добавляем текст
if not text.endswith('\n'):
text += '\n'
@@ -721,6 +737,9 @@ class TerminalWidget(CustomText):
# Автоматическая прокрутка к концу
self.see(tk.END)
# Возвращаем состояние "только для чтения"
self.config(state='disabled')
# Обновляем виджет
self.update_idletasks()
@@ -738,6 +757,9 @@ class TerminalWidget(CustomText):
def append_command(self, text):
"""Добавление команды с разделителем"""
# Временно разрешаем изменение для добавления текста
self.config(state='normal')
# Добавляем разделитель между командами
if self.command_counter > 0:
self.insert(tk.END, "\n" + "" * 80 + "\n", "separator")
@@ -745,10 +767,15 @@ class TerminalWidget(CustomText):
# Добавляем команду
self.append_text(text, "command")
# Возвращаем состояние "только для чтения"
self.config(state='disabled')
def clear(self):
"""Очистка терминала"""
self.config(state='normal')
self.delete("1.0", tk.END)
self.config(state='disabled')
self.command_counter = 0
# Основной класс для графического интерфейса
@@ -944,6 +971,14 @@ class SerialAppGUI(tk.Tk):
)
disconnect_btn.pack(side=LEFT, padx=5)
# Кнопка очистки терминала
clear_btn = ttk.Button(
control_frame,
text="🗑 Очистить", # Unicode символ для "корзины"
command=lambda: self.interactive_text.clear()
)
clear_btn.pack(side=LEFT, padx=5)
# Используем новый TerminalWidget вместо CustomText
self.interactive_text = TerminalWidget(frame, height=20)
self.interactive_text.pack(fill=BOTH, expand=True, padx=5, pady=5)
@@ -1107,6 +1142,10 @@ class SerialAppGUI(tk.Tk):
self.stop_button = ttk.Button(control_frame, text="⏹ Остановить", command=self.stop_execution, state="disabled")
self.stop_button.pack(side=LEFT, padx=5)
# Кнопка очистки терминала
self.clear_button = ttk.Button(control_frame, text="🗑 Очистить", command=lambda: self.file_exec_text.clear())
self.clear_button.pack(side=LEFT, padx=5)
# Создаем фрейм для индикатора прогресса и таймера
progress_frame = ttk.Frame(frame)
progress_frame.pack(fill=X, pady=5, padx=5)
@@ -1197,20 +1236,30 @@ class SerialAppGUI(tk.Tk):
def check_connection():
"""Проверка состояния соединения"""
# Если выполнение остановлено пользователем, просто возвращаем False без сообщений
if self.execution_stop:
return False
if not self.connection or not self.connection.is_open:
# Если остановка произошла во время проверки, не показываем сообщение
if self.execution_stop:
return False
self.append_file_exec_text("[ERROR] Соединение потеряно!\n")
# Автоматически ставим на паузу
self.execution_paused = True
self.after(0, lambda: self.pause_button.config(text="▶ Продолжить"))
# Показываем сообщение пользователю
self.after(0, lambda: messagebox.showerror(
"Ошибка соединения",
"Соединение с устройством потеряно!\nВыполнение команд приостановлено.\n\n"
"Пожалуйста:\n"
"1. Проверьте подключение\n"
"2. Нажмите 'Продолжить' после восстановления соединения\n"
" или 'Остановить' для прекращения выполнения"
))
# Показываем сообщение только если это не ручная остановка
if not self.execution_stop:
self.after(0, lambda: messagebox.showerror(
"Ошибка соединения",
"Соединение с устройством потеряно!\nВыполнение команд приостановлено.\n\n"
"Пожалуйста:\n"
"1. Проверьте подключение\n"
"2. Нажмите 'Продолжить' после восстановления соединения\n"
" или 'Остановить' для прекращения выполнения"
))
return False
return True
@@ -1582,6 +1631,14 @@ class SerialAppGUI(tk.Tk):
state="disabled"
)
self.stop_tftp_button.pack(side=LEFT, padx=5)
# Кнопка очистки лога
self.clear_tftp_button = ttk.Button(
buttons_frame,
text="🗑 Очистить лог",
command=lambda: self.tftp_log_text.clear()
)
self.clear_tftp_button.pack(side=LEFT, padx=5)
# Лог сервера
log_frame = ttk.LabelFrame(tftp_frame, text="Лог сервера")