Proper mismatch displaying in gui

This commit is contained in:
dazedanon 2026-02-17 15:59:24 -06:00
parent b0f2013f04
commit 0f2521f8d6
3 changed files with 56 additions and 11 deletions

View file

@ -9,6 +9,7 @@ from PyQt5.QtCore import Qt, pyqtSignal, QTimer
from PyQt5.QtGui import QTextCursor, QFont
from pathlib import Path
import datetime
import html
import os
@ -16,6 +17,7 @@ class LogViewer(QWidget):
"""Widget for viewing translation logs and monitoring progress."""
log_updated = pyqtSignal(str)
mismatch_detected = pyqtSignal() # Emitted each time a [MISMATCH] header line is seen
def __init__(self):
super().__init__()
@ -225,11 +227,20 @@ class LogViewer(QWidget):
self.stop_tail()
def append_log_message(self, message):
"""Append a message to the log display."""
# Append raw message (worker already includes any desired context).
# We intentionally avoid adding timestamps here so wrapped lines stay
# readable and do not misalign JSON-like outputs.
self.log_display.append(message)
"""Append a message to the log display.
Lines containing '[MISMATCH]' are rendered in red to highlight
translation batch failures.
"""
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()
else:
self.log_display.append(message)
# Scroll to bottom
cursor = self.log_display.textCursor()

View file

@ -855,8 +855,8 @@ class TranslationTab(QWidget):
# Place both buttons on the left and totals on the right
buttons_container = QWidget()
# Prevent the buttons row from changing the file list box size when
# buttons/totals are shown — keep a fixed height for the row.
buttons_container.setFixedHeight(64)
# buttons/totals are shown — use minimum height that can grow if needed.
buttons_container.setMinimumHeight(64)
buttons_container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
buttons_hbox = QHBoxLayout()
buttons_hbox.setContentsMargins(0, 0, 0, 0)
@ -869,10 +869,9 @@ class TranslationTab(QWidget):
buttons_hbox.addStretch()
# Totals widget on the right (hidden until start)
self.totals_widget = QWidget()
# Keep totals widget a fixed height so showing it doesn't expand the
# input files box vertically.
self.totals_widget.setFixedHeight(64)
self.totals_widget.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
# Let the totals widget size naturally; the mismatch label starts hidden
# so it won't take extra space until a mismatch occurs.
self.totals_widget.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)
totals_layout = QVBoxLayout()
totals_layout.setContentsMargins(6, 2, 6, 2)
totals_layout.setSpacing(2)
@ -885,6 +884,10 @@ class TranslationTab(QWidget):
self.totals_time_label = QLabel("Time: 0.0s")
self.totals_time_label.setStyleSheet("color: #4da6ff; font-weight: bold;")
totals_layout.addWidget(self.totals_time_label)
self.totals_mismatch_label = QLabel("")
self.totals_mismatch_label.setStyleSheet("color: #ff4444; font-weight: bold;")
self.totals_mismatch_label.setVisible(False)
totals_layout.addWidget(self.totals_mismatch_label)
self.totals_widget.setLayout(totals_layout)
self.totals_widget.setVisible(False)
buttons_hbox.addWidget(self.totals_widget)
@ -1014,6 +1017,7 @@ class TranslationTab(QWidget):
# Right side - translation history log viewer
self.translation_log_viewer = LogViewer()
self.translation_log_viewer.mismatch_detected.connect(self.on_mismatch_detected)
# Allow both left and right widgets to expand vertically so the
# log viewer fills the full height to the bottom of the tab.
@ -1643,6 +1647,10 @@ class TranslationTab(QWidget):
self.totals_cost_label.setText("Cost: $0.0000")
if hasattr(self, 'totals_time_label'):
self.totals_time_label.setText("Time: 0.0s")
if hasattr(self, 'totals_mismatch_label'):
self.totals_mismatch_label.setText("")
self.totals_mismatch_label.setVisible(False)
self.totals_mismatch_count = 0
if hasattr(self, 'totals_widget') and self.totals_widget:
self.totals_widget.setVisible(True)
except Exception:
@ -1858,6 +1866,18 @@ class TranslationTab(QWidget):
"""Handle a file translation error."""
# Mark the file as failed with the error message
self.mark_file_complete(filename, success=False, error_message=error_message)
def on_mismatch_detected(self):
"""Increment the mismatch counter and update the totals label."""
try:
if not hasattr(self, 'totals_mismatch_count'):
self.totals_mismatch_count = 0
self.totals_mismatch_count += 1
if hasattr(self, 'totals_mismatch_label'):
self.totals_mismatch_label.setText(f"Mismatches: {self.totals_mismatch_count}")
self.totals_mismatch_label.setVisible(True)
except Exception:
pass
def flush_log_buffer(self):
"""No longer needed - kept for compatibility."""

View file

@ -1276,6 +1276,20 @@ def translateAI(text, history, fullPromptFlag, config, filename=None, pbar=None,
mismatchFile.write(f"Final Output:\n{formatted_mismatch_output}\n")
mismatchFile.flush() # Ensure data is written to disk immediately
# Also write to the main translation log so the GUI log viewer can display it
try:
with open(config.logFilePath, "a", encoding="utf-8") as logFile:
logFile.write(f"[MISMATCH] Failed after retries: {filename}\n")
logFile.write(f"[MISMATCH] Input:\n")
for mline in subbedT.splitlines():
logFile.write(f"[MISMATCH] {mline}\n")
logFile.write(f"[MISMATCH] Final Output:\n")
for mline in formatted_mismatch_output.splitlines():
logFile.write(f"[MISMATCH] {mline}\n")
logFile.flush()
except Exception:
pass # Don't fail if logging fails
if filename and mismatchList is not None and filename not in mismatchList:
mismatchList.append(filename)