Initialer Push, Grundsätzlich funktioniert das Programm

This commit is contained in:
2026-07-09 23:00:31 +02:00
parent 70088f7861
commit 952bbb6158
51 changed files with 3066 additions and 0 deletions
+142
View File
@@ -0,0 +1,142 @@
"""Tab 3 - Processing: Instructions/Notes editieren, KI-Zusammenfassung anstoßen.
Ausgegraut, solange kein Transkript existiert (siehe MainWindow-Tab-Aktivierungslogik).
"""
from __future__ import annotations
import logging
from PySide6.QtCore import Signal
from PySide6.QtWidgets import QHBoxLayout, QLabel, QMessageBox, QPushButton, QTextEdit, QVBoxLayout, QWidget
from notarius.gui.controller import AppController
from notarius.gui.format_utils import format_duration, format_timestamp
from notarius.keyring_store import get_api_key
from notarius.models.recording import Recording
from notarius.summarization.worker import SummarizationWorker
logger = logging.getLogger(__name__)
class ProcessingTab(QWidget):
# MainWindow öffnet daraufhin automatisch Tab 4 und prüft die Tab-Aktivierung neu.
summarization_finished = Signal()
def __init__(self, controller: AppController, parent: QWidget | None = None) -> None:
super().__init__(parent)
self._controller = controller
self._recording: Recording | None = None
self._worker = SummarizationWorker()
self._header_label = QLabel()
self._header_label.setWordWrap(True)
self._notes_edit = QTextEdit()
self._notes_edit.setPlaceholderText(
"Zusatzinfos für die KI: Zuordnung SPEAKER_00 -> Name, Projektkontext, "
"Teilnehmer, Kanal, Datum, ..."
)
self._notes_save_button = QPushButton("Save")
self._notes_save_button.clicked.connect(self._on_notes_save_clicked)
self._summarize_button = QPushButton("Summarize")
self._summarize_button.clicked.connect(self._on_summarize_clicked)
self._status_label = QLabel("idle")
action_row = QHBoxLayout()
action_row.addWidget(self._summarize_button)
action_row.addWidget(self._status_label)
action_row.addStretch(1)
layout = QVBoxLayout(self)
layout.addWidget(self._header_label)
layout.addWidget(QLabel("<b>Instructions and Notes</b>"))
layout.addWidget(self._notes_edit, stretch=1)
layout.addWidget(self._notes_save_button)
layout.addLayout(action_row)
self.set_recording(None)
def set_recording(self, recording: Recording | None) -> None:
self._recording = recording
has_recording = recording is not None
self.setEnabled(has_recording)
if not has_recording:
return
self._header_label.setText(
f"<b>Titel:</b> {recording.meta.title}<br>"
f"<b>Aufzeichnungszeitpunkt:</b> {format_timestamp(recording.meta.created_at)}<br>"
f"<b>Länge:</b> {format_duration(recording.meta.duration_seconds)}<br>"
f"<b>Sprecher:</b> {', '.join(recording.meta.speakers) or '-'}"
)
if recording.prompt_notes_path.exists():
self._notes_edit.setPlainText(recording.prompt_notes_path.read_text(encoding="utf-8"))
else:
self._notes_edit.clear()
self._status_label.setText("ready" if recording.has_summary else "idle")
self._summarize_button.setText("Summarize")
self._summarize_button.setEnabled(True)
def _on_notes_save_clicked(self) -> None:
if self._recording is None:
return
self._recording.prompt_notes_path.write_text(self._notes_edit.toPlainText(), encoding="utf-8")
def _on_summarize_clicked(self) -> None:
if self._worker.is_running:
self._worker.cancel()
return
if self._recording is None:
return
api_key = get_api_key()
if not api_key:
QMessageBox.information(
self, "Kein API-Key", "Bitte zuerst in Tab 5 (Settings) einen Anthropic-API-Key hinterlegen."
)
return
if self._recording.has_summary:
answer = QMessageBox.question(
self, "Summary überschreiben?", "Es existiert bereits eine Summary. Überschreiben?"
)
if answer != QMessageBox.StandardButton.Yes:
return
transcript_markdown = self._recording.transcript_path.read_text(encoding="utf-8")
notes = self._notes_edit.toPlainText()
self._summarize_button.setText("Stop")
self._status_label.setText("processing")
self._worker.start(
api_key,
self._controller.config.claude_model,
transcript_markdown,
notes,
self._on_summary_ok,
self._on_summary_error,
self._on_summary_cancelled,
)
def _on_summary_ok(self, summary_markdown: str) -> None:
if self._recording is None:
return
self._recording.summary_path.write_text(summary_markdown, encoding="utf-8")
self._summarize_button.setText("Summarize")
self._status_label.setText("ready")
self.summarization_finished.emit()
def _on_summary_error(self, error_message: str) -> None:
self._summarize_button.setText("Summarize")
self._status_label.setText("error")
QMessageBox.critical(self, "Zusammenfassung fehlgeschlagen", error_message)
def _on_summary_cancelled(self) -> None:
self._summarize_button.setText("Summarize")
self._status_label.setText("idle")