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:
@@ -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="Лог сервера")
|
||||
|
||||
Reference in New Issue
Block a user