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 PyQt5.QtGui import QTextCursor, QFont
from pathlib import Path from pathlib import Path
import datetime import datetime
import html
import os import os
@ -16,6 +17,7 @@ class LogViewer(QWidget):
"""Widget for viewing translation logs and monitoring progress.""" """Widget for viewing translation logs and monitoring progress."""
log_updated = pyqtSignal(str) log_updated = pyqtSignal(str)
mismatch_detected = pyqtSignal() # Emitted each time a [MISMATCH] header line is seen
def __init__(self): def __init__(self):
super().__init__() super().__init__()
@ -225,11 +227,20 @@ class LogViewer(QWidget):
self.stop_tail() self.stop_tail()
def append_log_message(self, message): def append_log_message(self, message):
"""Append a message to the log display.""" """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 Lines containing '[MISMATCH]' are rendered in red to highlight
# readable and do not misalign JSON-like outputs. translation batch failures.
self.log_display.append(message) """
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 # Scroll to bottom
cursor = self.log_display.textCursor() 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 # Place both buttons on the left and totals on the right
buttons_container = QWidget() buttons_container = QWidget()
# Prevent the buttons row from changing the file list box size when # Prevent the buttons row from changing the file list box size when
# buttons/totals are shown — keep a fixed height for the row. # buttons/totals are shown — use minimum height that can grow if needed.
buttons_container.setFixedHeight(64) buttons_container.setMinimumHeight(64)
buttons_container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) buttons_container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
buttons_hbox = QHBoxLayout() buttons_hbox = QHBoxLayout()
buttons_hbox.setContentsMargins(0, 0, 0, 0) buttons_hbox.setContentsMargins(0, 0, 0, 0)
@ -869,10 +869,9 @@ class TranslationTab(QWidget):
buttons_hbox.addStretch() buttons_hbox.addStretch()
# Totals widget on the right (hidden until start) # Totals widget on the right (hidden until start)
self.totals_widget = QWidget() self.totals_widget = QWidget()
# Keep totals widget a fixed height so showing it doesn't expand the # Let the totals widget size naturally; the mismatch label starts hidden
# input files box vertically. # so it won't take extra space until a mismatch occurs.
self.totals_widget.setFixedHeight(64) self.totals_widget.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)
self.totals_widget.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
totals_layout = QVBoxLayout() totals_layout = QVBoxLayout()
totals_layout.setContentsMargins(6, 2, 6, 2) totals_layout.setContentsMargins(6, 2, 6, 2)
totals_layout.setSpacing(2) totals_layout.setSpacing(2)
@ -885,6 +884,10 @@ class TranslationTab(QWidget):
self.totals_time_label = QLabel("Time: 0.0s") self.totals_time_label = QLabel("Time: 0.0s")
self.totals_time_label.setStyleSheet("color: #4da6ff; font-weight: bold;") self.totals_time_label.setStyleSheet("color: #4da6ff; font-weight: bold;")
totals_layout.addWidget(self.totals_time_label) 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.setLayout(totals_layout)
self.totals_widget.setVisible(False) self.totals_widget.setVisible(False)
buttons_hbox.addWidget(self.totals_widget) buttons_hbox.addWidget(self.totals_widget)
@ -1014,6 +1017,7 @@ class TranslationTab(QWidget):
# Right side - translation history log viewer # Right side - translation history log viewer
self.translation_log_viewer = LogViewer() 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 # Allow both left and right widgets to expand vertically so the
# log viewer fills the full height to the bottom of the tab. # 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") self.totals_cost_label.setText("Cost: $0.0000")
if hasattr(self, 'totals_time_label'): if hasattr(self, 'totals_time_label'):
self.totals_time_label.setText("Time: 0.0s") 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: if hasattr(self, 'totals_widget') and self.totals_widget:
self.totals_widget.setVisible(True) self.totals_widget.setVisible(True)
except Exception: except Exception:
@ -1858,6 +1866,18 @@ class TranslationTab(QWidget):
"""Handle a file translation error.""" """Handle a file translation error."""
# Mark the file as failed with the error message # Mark the file as failed with the error message
self.mark_file_complete(filename, success=False, error_message=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): def flush_log_buffer(self):
"""No longer needed - kept for compatibility.""" """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.write(f"Final Output:\n{formatted_mismatch_output}\n")
mismatchFile.flush() # Ensure data is written to disk immediately 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: if filename and mismatchList is not None and filename not in mismatchList:
mismatchList.append(filename) mismatchList.append(filename)