Add advanced TerminalWidget with enhanced text display and formatting
- Implement TerminalWidget class with color-coded message types - Add support for error, warning, info, and command message styles - Include automatic scrollbar and text formatting - Replace CustomText with TerminalWidget in interactive tabs - Enhance text appending methods with type-specific display - Improve terminal readability with command separators
This commit is contained in:
138
ComConfigCopy.py
138
ComConfigCopy.py
@@ -670,6 +670,86 @@ def send_command_and_process_response(
|
||||
logging.error(msg)
|
||||
return False, None
|
||||
|
||||
# Класс для терминального виджета с расширенной функциональностью
|
||||
class TerminalWidget(CustomText):
|
||||
def __init__(self, master, *args, **kwargs):
|
||||
super().__init__(master, *args, **kwargs)
|
||||
|
||||
# Настройка цветов для разных типов сообщений
|
||||
self.tag_configure("error", foreground="red")
|
||||
self.tag_configure("warning", foreground="orange")
|
||||
self.tag_configure("info", foreground="blue")
|
||||
self.tag_configure("command", foreground="green")
|
||||
self.tag_configure("separator", foreground="gray")
|
||||
|
||||
# Добавляем скроллбар
|
||||
self.scrollbar = ttk.Scrollbar(self, command=self.yview)
|
||||
self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
|
||||
self.config(yscrollcommand=self.scrollbar.set)
|
||||
|
||||
# Настройка отступов и переносов
|
||||
self.config(
|
||||
wrap=tk.WORD,
|
||||
padx=5,
|
||||
pady=5,
|
||||
spacing1=2, # Отступ перед абзацем
|
||||
spacing2=2, # Межстрочный интервал
|
||||
spacing3=2 # Отступ после абзаца
|
||||
)
|
||||
|
||||
# Счетчик команд для разделителей
|
||||
self.command_counter = 0
|
||||
|
||||
def append_text(self, text, message_type=None):
|
||||
"""
|
||||
Добавление текста с определенным типом сообщения
|
||||
message_type может быть: 'error', 'warning', 'info', 'command'
|
||||
"""
|
||||
# Добавляем разделитель между командами
|
||||
if message_type == "command":
|
||||
if self.command_counter > 0:
|
||||
self.insert(tk.END, "\n" + "─" * 80 + "\n", "separator")
|
||||
self.command_counter += 1
|
||||
|
||||
# Добавляем текст
|
||||
if not text.endswith('\n'):
|
||||
text += '\n'
|
||||
|
||||
start_index = self.index(tk.END)
|
||||
self.insert(tk.END, text)
|
||||
end_index = self.index(tk.END)
|
||||
|
||||
# Применяем тег в зависимости от типа сообщения
|
||||
if message_type:
|
||||
self.tag_add(message_type, start_index, end_index)
|
||||
|
||||
# Автоматическая прокрутка к концу
|
||||
self.see(tk.END)
|
||||
|
||||
# Обновляем виджет
|
||||
self.update_idletasks()
|
||||
|
||||
def append_error(self, text):
|
||||
"""Добавление сообщения об ошибке"""
|
||||
self.append_text(text, "error")
|
||||
|
||||
def append_warning(self, text):
|
||||
"""Добавление предупреждения"""
|
||||
self.append_text(text, "warning")
|
||||
|
||||
def append_info(self, text):
|
||||
"""Добавление информационного сообщения"""
|
||||
self.append_text(text, "info")
|
||||
|
||||
def append_command(self, text):
|
||||
"""Добавление команды"""
|
||||
self.append_text(text, "command")
|
||||
|
||||
def clear(self):
|
||||
"""Очистка терминала"""
|
||||
self.delete("1.0", tk.END)
|
||||
self.command_counter = 0
|
||||
|
||||
# Основной класс для графического интерфейса
|
||||
class SerialAppGUI(tk.Tk):
|
||||
def __init__(self, settings):
|
||||
@@ -849,7 +929,8 @@ class SerialAppGUI(tk.Tk):
|
||||
)
|
||||
disconnect_btn.pack(side=LEFT, padx=5)
|
||||
|
||||
self.interactive_text = CustomText(frame, wrap="word", height=20)
|
||||
# Используем новый TerminalWidget вместо CustomText
|
||||
self.interactive_text = TerminalWidget(frame, height=20)
|
||||
self.interactive_text.pack(fill=BOTH, expand=True, padx=5, pady=5)
|
||||
|
||||
input_frame = ttk.Frame(frame)
|
||||
@@ -876,10 +957,10 @@ class SerialAppGUI(tk.Tk):
|
||||
return
|
||||
self.connection = create_connection(self.settings)
|
||||
if self.connection:
|
||||
self.append_interactive_text("[INFO] Подключение установлено.\n")
|
||||
self.interactive_text.append_info("[INFO] Подключение установлено.")
|
||||
self.update_status_bar() # Обновляем статус бар
|
||||
else:
|
||||
self.append_interactive_text("[ERROR] Не удалось установить соединение.\n")
|
||||
self.interactive_text.append_error("[ERROR] Не удалось установить соединение.")
|
||||
|
||||
# Отключение от устройства
|
||||
def disconnect_device(self):
|
||||
@@ -889,7 +970,7 @@ class SerialAppGUI(tk.Tk):
|
||||
except Exception:
|
||||
pass
|
||||
self.connection = None
|
||||
self.append_interactive_text("[INFO] Соединение закрыто.\n")
|
||||
self.interactive_text.append_info("[INFO] Соединение закрыто.")
|
||||
self.update_status_bar() # Обновляем статус бар
|
||||
else:
|
||||
messagebox.showinfo("Информация", "Соединение не установлено.")
|
||||
@@ -902,7 +983,7 @@ class SerialAppGUI(tk.Tk):
|
||||
cmd = self.command_entry.get().strip()
|
||||
if not cmd:
|
||||
return
|
||||
self.append_interactive_text(f"[INFO] Отправка команды: {cmd}\n")
|
||||
self.interactive_text.append_command(f"[CMD] {cmd}")
|
||||
threading.Thread(target=self.process_command, args=(cmd,), daemon=True).start()
|
||||
|
||||
# Обработка команды
|
||||
@@ -919,15 +1000,22 @@ class SerialAppGUI(tk.Tk):
|
||||
is_gui=True
|
||||
)
|
||||
except SerialException as e:
|
||||
self.append_interactive_text(f"[ERROR] Ошибка при отправке команды: {e}\n")
|
||||
self.interactive_text.append_error(f"[ERROR] Ошибка при отправке команды: {e}")
|
||||
logging.error(f"Ошибка отправки команды: {e}", exc_info=True)
|
||||
except Exception as e:
|
||||
self.append_interactive_text(f"[ERROR] Неизвестная ошибка: {e}\n")
|
||||
self.interactive_text.append_error(f"[ERROR] Неизвестная ошибка: {e}")
|
||||
logging.error(f"Неизвестная ошибка: {e}", exc_info=True)
|
||||
|
||||
# Добавление текста в текстовое поле
|
||||
def append_interactive_text(self, text):
|
||||
append_text_to_widget(self.interactive_text, text)
|
||||
if "[ERROR]" in text:
|
||||
self.interactive_text.append_error(text)
|
||||
elif "[WARNING]" in text or "[WARN]" in text:
|
||||
self.interactive_text.append_warning(text)
|
||||
elif "[INFO]" in text:
|
||||
self.interactive_text.append_info(text)
|
||||
else:
|
||||
self.interactive_text.append_text(text)
|
||||
|
||||
# Создание вкладки "Выполнить команды из файла"
|
||||
def create_file_exec_tab(self, frame):
|
||||
@@ -938,9 +1026,21 @@ class SerialAppGUI(tk.Tk):
|
||||
CustomEntry(file_frame, textvariable=self.file_exec_var, width=40).pack(side=LEFT, padx=5)
|
||||
ttk.Button(file_frame, text="Выбрать", command=self.select_config_file_fileexec).pack(side=LEFT, padx=5)
|
||||
ttk.Button(frame, text="Выполнить команды", command=self.execute_file_commands).pack(pady=5)
|
||||
self.file_exec_text = CustomText(frame, wrap="word", height=15)
|
||||
|
||||
# Используем новый TerminalWidget вместо CustomText
|
||||
self.file_exec_text = TerminalWidget(frame, height=15)
|
||||
self.file_exec_text.pack(fill=BOTH, expand=True, padx=5, pady=5)
|
||||
|
||||
def append_file_exec_text(self, text):
|
||||
if "[ERROR]" in text:
|
||||
self.file_exec_text.append_error(text)
|
||||
elif "[WARNING]" in text or "[WARN]" in text:
|
||||
self.file_exec_text.append_warning(text)
|
||||
elif "[INFO]" in text:
|
||||
self.file_exec_text.append_info(text)
|
||||
else:
|
||||
self.file_exec_text.append_text(text)
|
||||
|
||||
# Выбор файла конфигурации для выполнения команд
|
||||
def select_config_file_fileexec(self):
|
||||
select_config_file(self, self.file_exec_var)
|
||||
@@ -974,9 +1074,6 @@ class SerialAppGUI(tk.Tk):
|
||||
daemon=True,
|
||||
).start()
|
||||
|
||||
def append_file_exec_text(self, text):
|
||||
append_text_to_widget(self.file_exec_text, text)
|
||||
|
||||
# Создание вкладки "Редактор конфигурационного файла"
|
||||
def create_config_editor_tab(self, frame):
|
||||
top_frame = ttk.Frame(frame)
|
||||
@@ -1084,13 +1181,9 @@ class SerialAppGUI(tk.Tk):
|
||||
log_frame = ttk.LabelFrame(tftp_frame, text="Лог сервера")
|
||||
log_frame.pack(fill=BOTH, expand=True, padx=5, pady=5)
|
||||
|
||||
self.tftp_log_text = CustomText(log_frame, wrap=tk.WORD, height=10)
|
||||
# Используем новый TerminalWidget вместо CustomText
|
||||
self.tftp_log_text = TerminalWidget(log_frame, height=10)
|
||||
self.tftp_log_text.pack(fill=BOTH, expand=True, padx=5, pady=5)
|
||||
|
||||
# Добавляем скроллбар для лога
|
||||
scrollbar = ttk.Scrollbar(self.tftp_log_text, command=self.tftp_log_text.yview)
|
||||
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
|
||||
self.tftp_log_text.config(yscrollcommand=scrollbar.set)
|
||||
|
||||
# Статус передач
|
||||
transfers_frame = ttk.LabelFrame(tftp_frame, text="Активные передачи")
|
||||
@@ -1242,7 +1335,14 @@ class SerialAppGUI(tk.Tk):
|
||||
self.stop_tftp_button.config(state="normal")
|
||||
|
||||
def append_tftp_log(self, text):
|
||||
append_text_to_widget(self.tftp_log_text, text)
|
||||
if "[ERROR]" in text:
|
||||
self.tftp_log_text.append_error(text)
|
||||
elif "[WARNING]" in text or "[WARN]" in text:
|
||||
self.tftp_log_text.append_warning(text)
|
||||
elif "[INFO]" in text:
|
||||
self.tftp_log_text.append_info(text)
|
||||
else:
|
||||
self.tftp_log_text.append_text(text)
|
||||
|
||||
# Обновление информации об активных передачах
|
||||
def update_transfers_info(self):
|
||||
|
||||
Reference in New Issue
Block a user