Source code for gui.utils.logger

# -*- coding: utf-8 -*-
"""
:File: gui/utils/gui_logger.py
:Author: Benjamin Jaedon Choi - https://github.com/saintbenjamin
:Affiliated Church: The Eulji-ro Presbyterian Church [대한예수교장로회(통합) 을지로교회]
:Address: The Eulji-ro Presbyterian Church, 24-10, Eulji-ro 20-gil, Jung-gu, Seoul 04549, South Korea
:Telephone: +82-2-2266-3070
:E-mail: euljirochurch [at] G.M.A.I.L. (replace [at] with @ and G.M.A.I.L as you understood.)
:License: MIT License with Attribution Requirement (see LICENSE file for details); Copyright (c) 2025 The Eulji-ro Presbyterian Church.

Provides GUI-specific logging helpers for EuljiroBible, including error dialog and log viewer.
"""

import os
from PySide6.QtWidgets import (
    QMessageBox, QTextEdit, QVBoxLayout, QPushButton, QWidget
)
from core.utils.logger import log_error
from core.config import paths

[docs] def log_error_with_dialog(parent, exception: Exception, title="Error", extra_message=None): """ Log an exception and show a critical dialog with an optional "View Error Log" action. This helper is intended for GUI-safe error reporting: - Always writes the exception to the application error log via `log_error()`. - Shows a QMessageBox with the error text (and optional extra context). - If the user selects "View Error Log", opens a `MonitorErrorLog` window. Args: parent (QWidget | None): Parent widget for the QMessageBox and log viewer window. If None, a standalone log viewer window is created. exception (Exception): The exception instance to log and present to the user. title (str): Dialog window title. extra_message (str | None): Optional context string shown above the exception message. Use this to explain what the app was trying to do when the error occurred. Returns: None """ log_error(exception) msg = str(exception) if extra_message: msg = f"{extra_message}\n\n{msg}" msg_box = QMessageBox(parent) msg_box.setIcon(QMessageBox.Critical) msg_box.setWindowTitle(title) msg_box.setText(msg) log_button = msg_box.addButton("View Error Log", QMessageBox.ActionRole) ok_button = msg_box.addButton("OK", QMessageBox.AcceptRole) msg_box.exec() try: # If user chooses to view error log, open MonitorErrorLog window if msg_box.clickedButton() == log_button: if parent is not None: parent.monitor_error_log = MonitorErrorLog(parent) parent.monitor_error_log.show() parent.monitor_error_log.raise_() parent.monitor_error_log.activateWindow() else: # Fallback in case no parent is provided global _monitor_error_log _monitor_error_log = MonitorErrorLog() _monitor_error_log.show() _monitor_error_log.raise_() _monitor_error_log.activateWindow() except Exception as e: log_error(e)
[docs] def handle_exception(exception, title="Error", user_message=None, parent=None): """ Handle an exception by logging it and showing a GUI dialog. This is a convenience wrapper around `log_error_with_dialog()` for use across the GUI. Use this when you want a single call site that: - logs the exception - displays a user-facing message (optional) - keeps consistent dialog titles Args: exception (Exception): The exception instance to handle. title (str): Dialog window title. user_message (str | None): Optional, user-friendly context message shown in the dialog. parent (QWidget | None): Parent widget for the dialog (and log viewer if opened). Returns: None """ log_error_with_dialog(parent, exception, title=title, extra_message=user_message)
[docs] class MonitorErrorLog(QWidget): """ GUI window that displays the contents of the application's error log file. This viewer is used by error dialogs to let the user inspect `paths.LOG_FILE` without leaving the application. It renders the full file into a read-only QTextEdit. Attributes: text_edit (QTextEdit): Read-only text area showing the error log content. close_button (QPushButton): Button to close the window. """
[docs] def __init__(self, parent=None): """ Initialize the error log viewer window and load current log contents. Args: parent (QWidget | None): Optional parent widget. Returns: None """ super().__init__(parent) self.setWindowTitle("Error Log") self.resize(700, 500) self.text_edit = QTextEdit(self) self.text_edit.setReadOnly(True) self.close_button = QPushButton("Close") self.close_button.clicked.connect(self.close) layout = QVBoxLayout() layout.addWidget(self.text_edit) layout.addWidget(self.close_button) self.setLayout(layout) self.load_log()
[docs] def load_log(self): """ Load `paths.LOG_FILE` and display its contents in the viewer text area. Behavior: - If the log file does not exist, the viewer stays empty. - Any read failure is logged via `log_error()` (no dialog recursion). Returns: None """ try: if os.path.exists(paths.LOG_FILE): with open(paths.LOG_FILE, "r", encoding="utf-8") as f: content = f.read() self.text_edit.setPlainText(content) except Exception as e: log_error(e)