From 169cb1360be7325620df1a8ebd60f7f09f9b8c48 Mon Sep 17 00:00:00 2001 From: Tri Vo Khac Date: Wed, 28 Oct 2026 00:17:34 +0700 Subject: [PATCH] feat: show only the translated subtitle once translation finishes Co-Authored-By: Claude Opus 5.5 --- src/mpv/mpvitem.cpp | 20 +++++++++++++------- src/mpv/mpvitem.h | 11 ++++++----- src/qml/PlayerPage.qml | 2 +- src/qml/SubtitlePopup.qml | 2 +- src/translate/translationservice.h | 2 +- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/mpv/mpvitem.cpp b/src/mpv/mpvitem.cpp index ef325ae..42d07d3 100644 --- a/src/mpv/mpvitem.cpp +++ b/src/mpv/mpvitem.cpp @@ -194,7 +194,7 @@ void MpvItem::addSubtitleFile(const QUrl &url) commandAsync(QStringList{QStringLiteral("sub-add"), localPathOrUrl(url), QStringLiteral("select")}); } -void MpvItem::showSecondarySubtitleFile(const QUrl &url, const QString &title) +void MpvItem::showTranslatedSubtitleFile(const QUrl &url, const QString &title) { if (!url.isValid()) { return; @@ -203,15 +203,21 @@ void MpvItem::showSecondarySubtitleFile(const QUrl &url, const QString &title) for (const QVariant &entry : std::as_const(m_subtitleTracks)) { const QVariantMap track = entry.toMap(); if (track.value(QStringLiteral("externalFilename")).toString() == path) { - setSecondarySubtitleId(track.value(QStringLiteral("id")).toInt()); + showOnlySubtitle(track.value(QStringLiteral("id")).toInt()); return; } } - // "auto" adds the track without selecting it; updateTracks() selects it as secondary. - m_pendingSecondaryPath = path; + // "auto" adds the track without selecting it; updateTracks() selects it once mpv lists it. + m_pendingTranslatedPath = path; commandAsync(QStringList{QStringLiteral("sub-add"), path, QStringLiteral("auto"), title}); } +void MpvItem::showOnlySubtitle(int id) +{ + setSubtitleId(id); + setSecondarySubtitleId(0); +} + void MpvItem::showText(const QString &text) { commandAsync(QStringList{QStringLiteral("show-text"), text}); @@ -330,9 +336,9 @@ void MpvItem::updateTracks(const QVariantList &trackList) {QStringLiteral("ffIndex"), track.value(QStringLiteral("ff-index"), -1).toInt()}, }); - if (!m_pendingSecondaryPath.isEmpty() && track.value(QStringLiteral("external-filename")).toString() == m_pendingSecondaryPath) { - m_pendingSecondaryPath.clear(); - setSecondarySubtitleId(id); + if (!m_pendingTranslatedPath.isEmpty() && track.value(QStringLiteral("external-filename")).toString() == m_pendingTranslatedPath) { + m_pendingTranslatedPath.clear(); + showOnlySubtitle(id); } } diff --git a/src/mpv/mpvitem.h b/src/mpv/mpvitem.h index 6c6891e..e650268 100644 --- a/src/mpv/mpvitem.h +++ b/src/mpv/mpvitem.h @@ -66,9 +66,9 @@ public: Q_INVOKABLE void seek(double seconds); // Adds an external subtitle file and makes it the primary subtitle. Q_INVOKABLE void addSubtitleFile(const QUrl &url); - // Shows \a url as the secondary subtitle, adding it first (named \a title) unless it - // is already loaded. - Q_INVOKABLE void showSecondarySubtitleFile(const QUrl &url, const QString &title); + // Makes \a url the only subtitle shown, adding it first (named \a title) unless it is + // already loaded. + Q_INVOKABLE void showTranslatedSubtitleFile(const QUrl &url, const QString &title); // Shows a short message on mpv's on-screen display. Q_INVOKABLE void showText(const QString &text); @@ -90,6 +90,7 @@ private: void setFileLoaded(bool loaded); void updateTracks(const QVariantList &trackList); void applyUserConfig(); + void showOnlySubtitle(int id); bool m_ready = false; QUrl m_pendingUrl; @@ -103,8 +104,8 @@ private: int m_subtitleId = 0; int m_secondarySubtitleId = 0; double m_subtitleDelay = 0.0; - // File added by showSecondarySubtitleFile() that should become secondary once mpv lists it. - QString m_pendingSecondaryPath; + // File added by showTranslatedSubtitleFile() that should be shown once mpv lists it. + QString m_pendingTranslatedPath; bool m_loadUserConfig = false; QStringList m_loadedUserConfigFiles; QStringList m_skippedUserOptions; diff --git a/src/qml/PlayerPage.qml b/src/qml/PlayerPage.qml index 3cae395..25d63fd 100644 --- a/src/qml/PlayerPage.qml +++ b/src/qml/PlayerPage.qml @@ -141,7 +141,7 @@ Kirigami.Page { TranslationService { id: translator onTranslated: (subtitleUrl, fromCache) => { - mpv.showSecondarySubtitleFile(subtitleUrl, + mpv.showTranslatedSubtitleFile(subtitleUrl, KI18n.i18nc("@item:inlistbox subtitle track, %1 is a language", "%1 (translated)", QtPotatoSettings.targetLanguage)) mpv.showText(fromCache ? KI18n.i18nc("@info:osd", "Loaded the saved translation") diff --git a/src/qml/SubtitlePopup.qml b/src/qml/SubtitlePopup.qml index a423d9e..e8eec1a 100644 --- a/src/qml/SubtitlePopup.qml +++ b/src/qml/SubtitlePopup.qml @@ -116,7 +116,7 @@ QQC2.Popup { text: KI18n.i18nc("@action:button", "Translate Subtitle into %1", QtPotatoSettings.targetLanguage) onClicked: popup.translator.translate(popup.mpv.currentUrl, popup.currentTrack, popup.mpv.mediaTitle) - QQC2.ToolTip.text: KI18n.i18nc("@info:tooltip", "Translates the subtitle chosen above and shows the result as the secondary subtitle") + QQC2.ToolTip.text: KI18n.i18nc("@info:tooltip", "Translates the subtitle chosen above and shows the result in its place") QQC2.ToolTip.visible: hovered QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay } diff --git a/src/translate/translationservice.h b/src/translate/translationservice.h index c0933c6..0b0795a 100644 --- a/src/translate/translationservice.h +++ b/src/translate/translationservice.h @@ -17,7 +17,7 @@ class QNetworkAccessManager; // Translates a whole subtitle track with an LLM, batch by batch, and caches the result -// as an .srt file that mpv can load as the secondary subtitle. +// as an .srt file that mpv can load as a subtitle track. class TranslationService : public QObject { Q_OBJECT