fixing up loggin

This commit is contained in:
dazedanon 2026-02-17 16:23:11 -06:00
parent 0f2521f8d6
commit d86999732c
3 changed files with 49 additions and 13 deletions

View file

@ -6,7 +6,7 @@ from PyQt5.QtWidgets import (
QWidget, QVBoxLayout, QTextEdit, QLabel, QSizePolicy
)
from PyQt5.QtCore import Qt, pyqtSignal, QTimer
from PyQt5.QtGui import QTextCursor, QFont
from PyQt5.QtGui import QTextCursor, QFont, QTextCharFormat
from pathlib import Path
import datetime
import html
@ -120,6 +120,9 @@ class LogViewer(QWidget):
def clear_log(self):
"""Clear the log display and reset tracking."""
self.log_display.clear()
# Reset the char format so the red color from previous [MISMATCH]
# HTML spans doesn't bleed into new plain-text appends.
self.log_display.setCurrentCharFormat(QTextCharFormat())
self.status_label.setText("Log cleared")
# Reset tail file pointer and buffer if active
self._tail_buffer = ""
@ -171,11 +174,26 @@ class LogViewer(QWidget):
self._tail_timer.start(self._tail_interval)
def stop_tail(self):
"""Stop tailing the log file and close internal file handle."""
"""Stop tailing the log file and close internal file handle.
Performs a final drain so no data written before this call is lost.
"""
try:
self._tail_timer.stop()
except Exception:
pass
# Final drain: read any remaining data before closing the handle
try:
self._poll_tail()
except Exception:
pass
# Flush any leftover partial line sitting in the buffer
if self._tail_buffer and self._tail_buffer.strip():
try:
self.append_log_message(self._tail_buffer)
except Exception:
pass
self._tail_buffer = ""
if self._tail_f:
try:
self._tail_f.close()
@ -235,12 +253,13 @@ class LogViewer(QWidget):
if "[MISMATCH]" in message:
escaped = html.escape(message)
self.log_display.append(f'<span style="color: #ff4444;">{escaped}</span>')
# Emit signal on the header line ("Failed after retries") so the
# counter increments once per mismatch event, not per line.
if "Failed after retries" in message:
self.mismatch_detected.emit()
# Counting is handled via stdout MISMATCH_EVENT markers in
# TranslationTab.append_log — the log viewer only handles display.
else:
self.log_display.append(message)
# Explicitly wrap in a white span so Qt doesn't inherit red from
# a preceding [MISMATCH] HTML append.
escaped = html.escape(message)
self.log_display.append(f'<span style="color: #ffffff;">{escaped}</span>')
# Scroll to bottom
cursor = self.log_display.textCursor()

View file

@ -814,8 +814,8 @@ class TranslationTab(QWidget):
self.reset_view_button.setStyleSheet(icon_btn_style)
self.open_translations_button.setStyleSheet(icon_btn_style)
# Ensure emoji/icons are readable
self.reset_view_button.setFont(QFont('', 12))
self.open_translations_button.setFont(QFont('', 12))
self.reset_view_button.setFont(QFont('Segoe UI', 12))
self.open_translations_button.setFont(QFont('Segoe UI', 12))
# Create the stop button here so it sits in the same row as the
# back/open buttons. Use a compact icon style to match them but
@ -849,7 +849,7 @@ class TranslationTab(QWidget):
self.stop_button.clicked.connect(self.stop_translation)
self.stop_button.setStyleSheet(stop_button_style)
# Slightly larger font for the emoji to make it visually clear
self.stop_button.setFont(QFont('', 14))
self.stop_button.setFont(QFont('Segoe UI', 14))
self.stop_button.setVisible(False)
# Place both buttons on the left and totals on the right
@ -1017,6 +1017,9 @@ class TranslationTab(QWidget):
# Right side - translation history log viewer
self.translation_log_viewer = LogViewer()
# Mismatch counting is driven by MISMATCH_EVENT stdout markers
# detected in append_log. The log_viewer signal is kept as a
# fallback for in-process mode (e.g. speaker-parse).
self.translation_log_viewer.mismatch_detected.connect(self.on_mismatch_detected)
# Allow both left and right widgets to expand vertically so the
@ -1743,6 +1746,11 @@ class TranslationTab(QWidget):
self.translation_worker.start()
def append_log(self, message):
# Detect mismatch markers emitted to stdout by translation.py.
# This is the primary, non-racy detection path for subprocess mode.
if isinstance(message, str) and message.startswith("MISMATCH_EVENT:"):
self.on_mismatch_detected()
return # marker is internal, not displayed
try:
pattern = r'^\W*(?P<filename>[^:]+):.*?\[Input:\s*(?P<input>\d+)\].*?\[Output:\s*(?P<output>\d+)\].*?\[Cost:\s*\$(?P<cost>[\d\.]+)\].*?\[(?P<time>[\d\.]+)s\]'
m = re.search(pattern, message)
@ -1941,10 +1949,11 @@ class TranslationTab(QWidget):
except Exception:
pass
# Stop tailing the log when finished
# Stop tailing the log after a short delay so the final poll
# can pick up any data written just before the worker finished.
try:
if hasattr(self, 'translation_log_viewer') and self.translation_log_viewer:
self.translation_log_viewer.stop_tail()
QTimer.singleShot(600, self.translation_log_viewer.stop_tail)
except Exception:
pass

View file

@ -1263,7 +1263,15 @@ def translateAI(text, history, fullPromptFlag, config, filename=None, pbar=None,
else: # Failure case after all retries
if pbar: pbar.write(f"Translation failed after {max_retries + 1} attempts. Check mismatch log.")
# Emit a machine-readable marker on stdout so the GUI worker
# thread can detect the mismatch reliably (stdout is captured
# synchronously, unlike file-tail polling which can be racy).
try:
print(f"MISMATCH_EVENT:{filename}", flush=True)
except Exception:
pass
formatted_mismatch_output = last_raw_translation
try:
parsed_json = json.loads(last_raw_translation)