refactor(ui): make 'fix unlined entries' panel refresh button use sync banner

This commit is contained in:
Travis Abendshien
2026-09-10 23:48:04 -07:00
parent e87b32a780
commit 2c87ce67db
25 changed files with 6 additions and 63 deletions
+1 -38
View File
@@ -4,24 +4,19 @@
from typing import TYPE_CHECKING, override
import structlog
from PySide6 import QtCore, QtGui
from PySide6.QtCore import Qt
from PySide6.QtWidgets import QHBoxLayout, QLabel, QPushButton, QVBoxLayout, QWidget
from tagstudio.core.library.alchemy.library import Library
from tagstudio.core.utils.types import unwrap
from tagstudio.i18n.translations import Translations
from tagstudio.qt.controllers.merge_dupe_entries_progress import MergeDuplicateEntriesProgress
from tagstudio.qt.controllers.progress_bar import ProgressWidget
from tagstudio.qt.mixed.remove_unlinked_modal import RemoveUnlinkedEntriesModal
from tagstudio.qt.views.styles.stylesheets import header
if TYPE_CHECKING:
from tagstudio.qt.qt_driver import QtDriver
logger = structlog.get_logger(__name__)
# TODO: Split to use MVC guidelines, or completely redo.
class FixUnlinkedEntriesModal(QWidget):
@@ -60,7 +55,7 @@ class FixUnlinkedEntriesModal(QWidget):
self.dupe_count_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.refresh_unlinked_button = QPushButton(Translations["entries.generic.refresh_alt"])
self.refresh_unlinked_button.clicked.connect(self.refresh_unlinked)
self.refresh_unlinked_button.clicked.connect(self.driver.sync_library_callback)
self.merge_class = MergeDuplicateEntriesProgress(self.lib, self.driver)
@@ -100,38 +95,6 @@ class FixUnlinkedEntriesModal(QWidget):
self.update_unlinked_count()
def refresh_unlinked(self):
if self.driver.file_scan_lock:
logger.info("[FixUnlinkedEntries] Sync already in progress, ignoring refresh request")
return
self.driver.file_scan_lock = True
pw = ProgressWidget(
cancel_button_text=None,
minimum=0,
maximum=self.lib.entries_count,
)
pw.setWindowTitle(Translations["library.scan_library.title"])
pw.update_label(Translations["entries.unlinked.scanning"])
def finish():
self.driver.file_scan_lock = False
if (
hasattr(self.driver, "library_info_window")
and self.driver.library_info_window.isVisible()
):
self.driver.library_info_window.update_cleanup()
# Uses the Library's shared path cache
pw.from_iterable_function(
lambda: self.sync_engine.sync_dir(unwrap(self.lib.library_dir)),
None,
self.set_unlinked_count,
finish,
self.update_unlinked_count,
self.remove_modal.refresh_list,
)
def _sync_ui_from_tracker(self) -> None:
"""Refresh the UI from the tracker's current state, without rescanning the library."""
self.set_unlinked_count()
+3
View File
@@ -1166,6 +1166,9 @@ class QtDriver(DriverMixin, QObject):
self.lib.unlinked_entries_count = unlinked_count
if hasattr(self, "unlinked_modal") and self.unlinked_modal.isVisible():
self.unlinked_modal.update_unlinked_count()
self.unlinked_modal.remove_modal.refresh_list()
if hasattr(self, "library_info_window") and self.library_info_window.isVisible():
self.library_info_window.update_cleanup()
if self.sync_engine.cancelled:
return
@@ -40,7 +40,6 @@
"entries.duplicates.description": "Duplicitní položky jsou definovány jako více položek, které ukazují na stejný soubor na disku. Jejich sloučením se spojí značky a metadata ze všech duplikátů do jediné konsolidované položky. Nesmí se zaměňovat s „duplicitními soubory“, což jsou duplikáty samotných vašich souborů mimo TagStudio.",
"entries.mirror.confirmation": "Opravdu chcete zrcadlit následujících {count} položek?",
"entries.unlinked.relink.manual": "Znovu propojit ručně",
"entries.unlinked.scanning": "Skenuji knihovnu pro nepropojené záznamy...",
"entries.unlinked.title": "Opravit nepropojené záznamy",
"field.copy": "Zkopírovat políčko",
"field.edit": "Upravit políčko",
@@ -62,7 +62,6 @@
"entries.unlinked.relink.manual": "&Manuell Neuverknüpfen",
"entries.unlinked.remove": "Entferne nicht verknüpfte Einträge",
"entries.unlinked.remove_alt": "Entfer&ne nicht verknüpfte Einträge",
"entries.unlinked.scanning": "Bibliothek wird nach nicht verknüpften Einträgen durchsucht...",
"entries.unlinked.title": "Unverknüpfte Einträge reparieren",
"entries.unlinked.unlinked_count": "Unverknüpfte Einträge: {count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status}<br>{ffprobe}: {ffprobe_status}",
@@ -61,7 +61,6 @@
"entries.unlinked.relink.manual": "&Χειροκίνητη επανασύνδεση",
"entries.unlinked.remove": "Αφαίρεση αποσυνδεδεμένων εγγραφών",
"entries.unlinked.remove_alt": "Α&φαίρεση αποσυνδεδεμένων εγγραφών",
"entries.unlinked.scanning": "Σάρωση βιβλιοθήκης για αποσυνδεδεμένες εγγραφές...",
"entries.unlinked.title": "Διόρθωση αποσυνδεδεμένων εγγραφών",
"entries.unlinked.unlinked_count": "Αποσυνδεδεμένες εγγραφές: {count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status}<br>{ffprobe}: {ffprobe_status}",
+2 -3
View File
@@ -67,10 +67,9 @@
"entries.unlinked.description.ambiguous": "For unlinked entries that have ambiguous matches to multiple files in your library, you may manually choose how they get relinked.",
"entries.unlinked.description.deleted": "When you delete files outside of TagStudio, their associated entries become unlinked. You may manually delete any unlinked entries at your own discretion.",
"entries.unlinked.relink.manual": "&Manual Relink",
"entries.unlinked.remove": "Remove Unlinked Entries",
"entries.unlinked.remove_alt": "Remo&ve Unlinked Entries",
"entries.unlinked.remove": "Delete Unlinked Entries",
"entries.unlinked.remove_alt": "&Delete Unlinked Entries",
"entries.unlinked.review": "Manual &Review",
"entries.unlinked.scanning": "Scanning Library for Unlinked Entries…",
"entries.unlinked.title": "Fix Unlinked Entries",
"entries.unlinked.unlinked_count": "Unlinked Entries: {count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status}<br>{ffprobe}: {ffprobe_status}",
@@ -65,7 +65,6 @@
"entries.unlinked.relink.manual": "&Reenlace manual",
"entries.unlinked.remove": "Eliminar Entradas No Vinculadas",
"entries.unlinked.remove_alt": "Quit&ar entradas desvinculadas",
"entries.unlinked.scanning": "Buscando entradas no enlazadas en la biblioteca...",
"entries.unlinked.title": "Corregir entradas no vinculadas",
"entries.unlinked.unlinked_count": "Entradas no vinculadas: {count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status}<br>{ffprobe}: {ffprobe_status}",
@@ -61,7 +61,6 @@
"entries.unlinked.relink.manual": "&Manual Relink",
"entries.unlinked.remove": "Poista linkittämättömät merkinnät",
"entries.unlinked.remove_alt": "Remo&ve Unlinked Entries",
"entries.unlinked.scanning": "Skannataan kirjastosta linkittämättömiä merkintöjä...",
"entries.unlinked.title": "Korjaa linkittämättömät merkinnät",
"entries.unlinked.unlinked_count": "Linkittämättömät merkinnät: {count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status}<br>{ffprobe}: {ffprobe_status}",
@@ -50,7 +50,6 @@
"entries.tags": "Mga Tag",
"entries.unlinked.description": "Ang bawat entry sa library ay naka-link sa isang file sa isa sa iyong mga direktoryo. Kung ang isang file na naka-link sa isang entry ay inilipat o binura sa labas ng TagStudio, ito ay isinasaalang-alang na naka-unlink.",
"entries.unlinked.relink.manual": "&Manwal na Pag-link Muli",
"entries.unlinked.scanning": "Sina-scan ang Library para sa Mga Naka-unlink na Entry…",
"entries.unlinked.title": "Ayusin ang Mga Naka-unlink na Entry",
"entries.unlinked.unlinked_count": "Mga Naka-unlink na Entry: {count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status}<br>{ffprobe}: {ffprobe_status}",
@@ -66,7 +66,6 @@
"entries.unlinked.relink.manual": "&Reliage Manuel",
"entries.unlinked.remove": "Supprimer les entrées non liées",
"entries.unlinked.remove_alt": "Supprim&er les entrées non liées",
"entries.unlinked.scanning": "Balayage de la Bibliothèque pour trouver des Entrées non Liées...",
"entries.unlinked.title": "Réparation des Entrées non Liées",
"entries.unlinked.unlinked_count": "Entrées non Liées : {count}",
"ffmpeg.missing.status": "{ffmpeg} : {ffmpeg_status}<br>{ffprobe} : {ffprobe_status}",
@@ -66,7 +66,6 @@
"entries.unlinked.relink.manual": "Új&ra összekapcsolás kézileg",
"entries.unlinked.remove": "Kapcsolat nélküli elemek eltávolítása",
"entries.unlinked.remove_alt": "&Kapcsolat nélküli elemek eltávolítása",
"entries.unlinked.scanning": "Kapcsolat nélküli elemek keresése a könyvtárban…",
"entries.unlinked.title": "Kapcsolat nélküli elemek javítása",
"entries.unlinked.unlinked_count": "Kapcsolat nélküli elemek: {count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status}<br>{ffprobe}: {ffprobe_status}",
@@ -61,7 +61,6 @@
"entries.unlinked.relink.manual": "Ricollegamento &Manuale",
"entries.unlinked.remove": "Rimuovi Voci non Collegate",
"entries.unlinked.remove_alt": "Rimuo&vi Voci non Collegate",
"entries.unlinked.scanning": "Scansionando la Biblioteca in cerca di Voci non Collegate...",
"entries.unlinked.title": "Correggi Voci non Collegate",
"entries.unlinked.unlinked_count": "Voci non Collegate: {count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status}<br>{ffprobe}: {ffprobe_status}",
@@ -66,7 +66,6 @@
"entries.unlinked.relink.manual": "手動で再リンク(&M)",
"entries.unlinked.remove": "リンク切れのエントリを削除",
"entries.unlinked.remove_alt": "リンク切れのエントリを削除(&V)",
"entries.unlinked.scanning": "リンク切れのエントリをライブラリ内でスキャンしています…",
"entries.unlinked.title": "リンク切れのエントリを修正",
"entries.unlinked.unlinked_count": "リンク切れのエントリ数: {count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status}<br>{ffprobe}: {ffprobe_status}",
@@ -58,7 +58,6 @@
"entries.tags": "Etiketter",
"entries.unlinked.description": "Hver biblioteksoppføring er koblet til en fil i en av dine mapper. Hvis en fil koblet til en oppføring er flyttet eller slettet utenfor TagStudio, så er den sett på som frakoblet.",
"entries.unlinked.relink.manual": "&Manuell Gjenkobling",
"entries.unlinked.scanning": "Skanner bibliotek for ulenkede oppføringer …",
"entries.unlinked.title": "Fiks ulenkede oppføringer",
"entries.unlinked.unlinked_count": "Frakoblede Oppføringer: {count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status}<br>{ffprobe}: {ffprobe_status}",
@@ -50,7 +50,6 @@
"entries.tags": "Tagi",
"entries.unlinked.description": "Każdy wpis w bibliotece jest połączony z plikiem w jednym z twoich katalogów. Jeśli połączony plik jest przeniesiony poza TagStudio albo usunięty to jest uważany za odłączony.",
"entries.unlinked.relink.manual": "&Ręczne ponowne łączenie",
"entries.unlinked.scanning": "Skanowanie biblioteki dla odłączonych wpisów...",
"entries.unlinked.title": "Napraw odłączone wpisy",
"entries.unlinked.unlinked_count": "Odłączone wpisy: {count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status}<br>{ffprobe}: {ffprobe_status}",
@@ -56,7 +56,6 @@
"entries.unlinked.description": "Cada registo na biblioteca faz referência à um ficheiro numa das suas pastas. Se um ficheiro referenciado à uma entrada for movido ou apagado fora do TagStudio, ele é depois considerado não-referenciado.",
"entries.unlinked.relink.manual": "&Referência Manual",
"entries.unlinked.remove_alt": "Remover Entradas sem Conexões",
"entries.unlinked.scanning": "A escanear biblioteca por registos não referenciados...",
"entries.unlinked.title": "Corrigir Registos Não Referenciados",
"entries.unlinked.unlinked_count": "Registos Não Referenciados: {count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status}<br>{ffprobe}: {ffprobe_status}",
@@ -61,7 +61,6 @@
"entries.unlinked.relink.manual": "&Referência Manual",
"entries.unlinked.remove": "Remover Registros Não Vinculados",
"entries.unlinked.remove_alt": "Remover Entradas sem Conexões",
"entries.unlinked.scanning": "Escaneando bibliotecada em busca de registros não referenciados...",
"entries.unlinked.title": "Corrigir Registros Não Referenciados",
"entries.unlinked.unlinked_count": "Registros Não Referenciados: {count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status}<br>{ffprobe}: {ffprobe_status}",
@@ -61,7 +61,6 @@
"entries.unlinked.relink.manual": "&Tsunaga gen mit hant",
"entries.unlinked.remove": "Keste kntsunagajena shiruzmakaban",
"entries.unlinked.remove_alt": "Keste kntsunagajena shiruzmakaban (&v)",
"entries.unlinked.scanning": "Taskame mlafuhuomi ima grun kntsunagajena shiruzmakaban...",
"entries.unlinked.title": "Fiks kntsunagajena shiruzmakaban",
"entries.unlinked.unlinked_count": "Kntsunagajena shiruzmakaban: {count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status}<br>{ffprobe}: {ffprobe_status}",
@@ -62,7 +62,6 @@
"entries.unlinked.description": "Каждая запись в библиотеке привязана к файлу, находящегося внутри той или иной папки. Если файл, к которому была привязана запись, был удалён или перемещён без использования TagStudio, то запись становиться \"откреплённой\".",
"entries.unlinked.relink.manual": "&Ручная привязка",
"entries.unlinked.remove": "Удалить откреплённые записи",
"entries.unlinked.scanning": "Сканирование библиотеки на наличие откреплённых записей...",
"entries.unlinked.title": "Исправить откреплённые записи",
"entries.unlinked.unlinked_count": "Откреплённых записей: {count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status}<br>{ffprobe}: {ffprobe_status}",
@@ -61,7 +61,6 @@
"entries.unlinked.relink.manual": "Länka om manuellt",
"entries.unlinked.remove": "Ta Bort Olänkade Poster",
"entries.unlinked.remove_alt": "&Ta Bort Olänkade Poster",
"entries.unlinked.scanning": "Skannar bibliotek efter olänkade poster...",
"entries.unlinked.title": "Fixa olänkade poster",
"entries.unlinked.unlinked_count": "Olänkade Poster: {count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status}<br>{ffprobe}: {ffprobe_status}",
@@ -61,7 +61,6 @@
"entries.unlinked.relink.manual": "& கையேடு மறுபரிசீலனை",
"entries.unlinked.remove": "இணைக்கப்படாத உள்ளீடுகளை அகற்று",
"entries.unlinked.remove_alt": "இணைக்கப்படாத உள்ளீடுகளை அகற்று&விடு",
"entries.unlinked.scanning": "இணைக்கப்படாத நுழைவுகளை புத்தககல்லரியில் சோதனை செய்யப்படுகிறது...",
"entries.unlinked.title": "இணைக்கப்படாத உள்ளீடுகளைச் சரிசெய்யவும்",
"entries.unlinked.unlinked_count": "இணைக்கப்படாத உள்ளீடுகள்: {count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status} <br> {ffprobe}: {ffprobe_status}",
@@ -60,7 +60,6 @@
"entries.unlinked.relink.manual": "sina o pana e ijo lon tawa ijo (&M)",
"entries.unlinked.remove": "o weka e ijo pi ijo lon ala",
"entries.unlinked.remove_alt": "o weka e ijo pi ijo lon ala (&V)",
"entries.unlinked.scanning": "mi o alasa e ijo pi ijo lon ala...",
"entries.unlinked.title": "o pona e ijo pi ijo lon ala",
"entries.unlinked.unlinked_count": "ijo pi ijo lon ala: {count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status}<br>{ffprobe}: {ffprobe_status}",
@@ -49,7 +49,6 @@
"entries.tags": "Etiketler",
"entries.unlinked.description": "Kütüphanenizdeki her bir kayıt, dizinlerinizden bir tane dosya ile eşleştirilmektedir. Eğer bir kayıta bağlı dosya TagStudio dışında taşınır veya silinirse, o dosya artık kopmuş olarak sayılır.",
"entries.unlinked.relink.manual": "&Manuel Yeniden Eşleştirme",
"entries.unlinked.scanning": "Kütüphane, Kopmuş Kayıtlar için Taranıyor...",
"entries.unlinked.title": "Kopmuş Kayıtları Düzelt",
"entries.unlinked.unlinked_count": "Kopmuş Kayıtlar: {count}",
"field.add": "Ek Bilgi Ekle",
@@ -60,7 +60,6 @@
"entries.unlinked.relink.manual": "手动重新链接(&m)",
"entries.unlinked.remove": "删除未链接项目",
"entries.unlinked.remove_alt": "删除未链接项目(&v)",
"entries.unlinked.scanning": "正在扫描仓库以寻找未链接的项目...",
"entries.unlinked.title": "修复未链接的项目",
"entries.unlinked.unlinked_count": "未链接的项目: {count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status}<br>{ffprobe}: {ffprobe_status}",
@@ -61,7 +61,6 @@
"entries.unlinked.relink.manual": "手動重新連接 (&M)",
"entries.unlinked.remove": "刪除未連接項目",
"entries.unlinked.remove_alt": "刪除未連接項目 (&V)",
"entries.unlinked.scanning": "正在掃描文件庫中的未連接項目...",
"entries.unlinked.title": "修復未連接項目",
"entries.unlinked.unlinked_count": "未連接項目:{count}",
"ffmpeg.missing.status": "{ffmpeg}: {ffmpeg_status}<br>{ffprobe}: {ffprobe_status}",