mirror of
https://github.com/TagStudioDev/TagStudio.git
synced 2026-05-26 10:42:48 +00:00
Compare commits
13 Commits
4dc06835cb
...
29db19c038
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29db19c038 | ||
|
|
ef61add296 | ||
|
|
e1234be8ac | ||
|
|
39d36f23ee | ||
|
|
733e5a881e | ||
|
|
db8958a64e | ||
|
|
1ee01f5f78 | ||
|
|
e4a23f6b5e | ||
|
|
e95b4104bb | ||
|
|
91af6260e0 | ||
|
|
15fa23e391 | ||
|
|
4592525cb4 | ||
|
|
c26934f258 |
@@ -7,7 +7,6 @@ import structlog
|
||||
from tagstudio.core.library.alchemy.enums import BrowsingState
|
||||
from tagstudio.core.library.alchemy.library import Library
|
||||
from tagstudio.core.library.alchemy.models import Entry
|
||||
from tagstudio.core.utils.types import unwrap
|
||||
|
||||
logger = structlog.get_logger()
|
||||
|
||||
@@ -29,7 +28,7 @@ class DupeFilesRegistry:
|
||||
A duplicate file is defined as an identical or near-identical file as determined
|
||||
by a DupeGuru results file.
|
||||
"""
|
||||
library_dir = unwrap(self.library.library_dir)
|
||||
library_dir = self.library.library_dir
|
||||
if not isinstance(results_filepath, Path):
|
||||
results_filepath = Path(results_filepath)
|
||||
|
||||
@@ -44,7 +43,7 @@ class DupeFilesRegistry:
|
||||
files: list[Entry] = []
|
||||
for element in group:
|
||||
if element.tag == "file":
|
||||
file_path = Path(unwrap(element.attrib.get("path")))
|
||||
file_path = Path(element.attrib.get("path"))
|
||||
|
||||
try:
|
||||
path_relative = file_path.relative_to(library_dir)
|
||||
@@ -83,5 +82,5 @@ class DupeFilesRegistry:
|
||||
for i, entries in enumerate(self.groups):
|
||||
remove_ids = entries[1:]
|
||||
logger.info("Removing entries group", ids=remove_ids)
|
||||
self.library.remove_entries([e.id for e in remove_ids])
|
||||
self.library.remove_entries(remove_ids)
|
||||
yield i - 1 # The -1 waits for the next step to finish
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
# Licensed under the GPL-3.0 License.
|
||||
# Created for TagStudio: https://github.com/CyanVoxel/TagStudio
|
||||
|
||||
# pyright: reportExplicitAny=false
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
@@ -522,7 +522,7 @@ class BuildTagPanel(PanelWidget):
|
||||
|
||||
self.alias_names.clear()
|
||||
|
||||
last: QWidget | None = self.panel_save_button
|
||||
last: QWidget = self.panel_save_button
|
||||
for alias_id in self.alias_ids:
|
||||
alias = self.lib.get_alias(self.tag.id, alias_id)
|
||||
|
||||
@@ -549,8 +549,7 @@ class BuildTagPanel(PanelWidget):
|
||||
self.aliases_table.setCellWidget(row, 1, new_item)
|
||||
self.aliases_table.setCellWidget(row, 0, remove_btn)
|
||||
|
||||
if last is not None:
|
||||
self.setTabOrder(last, self.aliases_table.cellWidget(row, 1))
|
||||
self.setTabOrder(last, self.aliases_table.cellWidget(row, 1))
|
||||
self.setTabOrder(
|
||||
self.aliases_table.cellWidget(row, 1), self.aliases_table.cellWidget(row, 0)
|
||||
)
|
||||
@@ -625,4 +624,3 @@ class BuildTagPanel(PanelWidget):
|
||||
self.setTabOrder(unwrap(self.panel_save_button), self.aliases_table.cellWidget(0, 1))
|
||||
self.name_field.selectAll()
|
||||
self.name_field.setFocus()
|
||||
self._set_aliases()
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
# Licensed under the GPL-3.0 License.
|
||||
# Created for TagStudio: https://github.com/CyanVoxel/TagStudio
|
||||
import re
|
||||
|
||||
import structlog
|
||||
|
||||
from PySide6.QtGui import QAction
|
||||
from PySide6.QtWidgets import QMenu
|
||||
|
||||
logger = structlog.get_logger(__name__)
|
||||
|
||||
|
||||
def remove_mnemonic_marker(label: str) -> str:
|
||||
"""Remove existing accelerator markers (&) from a label."""
|
||||
@@ -28,31 +25,6 @@ def remove_mnemonic_marker(label: str) -> str:
|
||||
return result
|
||||
|
||||
|
||||
def get_wanted_mnemonics(text: str) -> list[str]:
|
||||
matches = re.findall("(?:^|[^&])&([^&])", text)
|
||||
return matches
|
||||
|
||||
|
||||
def sanitise_mnemonics(actions: list[QAction]) -> None:
|
||||
previous = []
|
||||
for action in actions:
|
||||
text = action.text()
|
||||
m = get_wanted_mnemonics(text)
|
||||
|
||||
if len(m) == 0:
|
||||
continue
|
||||
elif len(m) > 1:
|
||||
logger.warning("Found multiple wanted mnemonics, removing all", text=text)
|
||||
action.setText(remove_mnemonic_marker(text))
|
||||
continue
|
||||
elif m[0] in previous:
|
||||
logger.warning("Removing conflicting mnemonic", text=text)
|
||||
action.setText(remove_mnemonic_marker(text))
|
||||
continue
|
||||
|
||||
previous.append(m[0])
|
||||
|
||||
|
||||
# Additional weight for first character in string
|
||||
FIRST_CHARACTER_EXTRA_WEIGHT = 50
|
||||
# Additional weight for the beginning of a word
|
||||
@@ -125,9 +97,6 @@ def assign_mnemonics(menu: QMenu):
|
||||
# Collect actions
|
||||
actions = [a for a in menu.actions() if not a.isSeparator()]
|
||||
|
||||
# sanitise mnemonics to prevent deadlocks
|
||||
sanitise_mnemonics(actions)
|
||||
|
||||
# Sequence map: mnemonic key -> QAction
|
||||
sequence_to_action: dict[str, QAction] = {}
|
||||
|
||||
|
||||
@@ -790,17 +790,25 @@ class ThumbRenderer(QObject):
|
||||
)
|
||||
im: Image.Image | None = None
|
||||
try:
|
||||
if (blend_image := blend_thumb(str(filepath))) is not None:
|
||||
bg = Image.new("RGB", blend_image.size, color=bg_color)
|
||||
bg.paste(blend_image, mask=blend_image.getchannel(3))
|
||||
im = bg
|
||||
else:
|
||||
blend_image = blend_thumb(str(filepath))
|
||||
|
||||
bg = Image.new("RGB", blend_image.size, color=bg_color)
|
||||
bg.paste(blend_image, mask=blend_image.getchannel(3))
|
||||
im = bg
|
||||
|
||||
except (
|
||||
AttributeError,
|
||||
UnidentifiedImageError,
|
||||
TypeError,
|
||||
) as e:
|
||||
if str(e) == "expected string or buffer":
|
||||
logger.info(
|
||||
f"[ThumbRenderer][BLENDER][INFO] {filepath.name} "
|
||||
"Doesn't have an embedded thumbnail."
|
||||
f"Doesn't have an embedded thumbnail. ({type(e).__name__})"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error("Couldn't render thumbnail", filepath=filepath, error=type(e).__name__)
|
||||
|
||||
else:
|
||||
logger.error("Couldn't render thumbnail", filepath=filepath, error=type(e).__name__)
|
||||
return im
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -32,7 +32,7 @@ from io import BufferedReader
|
||||
from PIL import Image, ImageOps
|
||||
|
||||
|
||||
def blend_extract_thumb(path) -> tuple[bytes | None, int, int]:
|
||||
def blend_extract_thumb(path):
|
||||
rend = b"REND"
|
||||
test = b"TEST"
|
||||
|
||||
@@ -97,10 +97,8 @@ def blend_extract_thumb(path) -> tuple[bytes | None, int, int]:
|
||||
return image_buffer, x, y
|
||||
|
||||
|
||||
def blend_thumb(file_in) -> Image.Image | None:
|
||||
def blend_thumb(file_in):
|
||||
buf, width, height = blend_extract_thumb(file_in)
|
||||
if buf is None:
|
||||
return None
|
||||
image = Image.frombuffer(
|
||||
"RGBA",
|
||||
(width, height),
|
||||
|
||||
@@ -383,7 +383,7 @@ class ThumbGridLayout(QLayout):
|
||||
@override
|
||||
def itemAt(self, index: int) -> QLayoutItem:
|
||||
if index >= len(self._items):
|
||||
return None # pyright: ignore[reportReturnType]
|
||||
return None
|
||||
return self._items[index]
|
||||
|
||||
@override
|
||||
|
||||
@@ -899,7 +899,6 @@ class QtDriver(DriverMixin, QObject):
|
||||
deleted_count: int = 0
|
||||
|
||||
selected = self.selected
|
||||
library_dir = unwrap(self.lib.library_dir)
|
||||
|
||||
if len(selected) <= 1 and origin_path:
|
||||
origin_id_ = origin_id
|
||||
@@ -908,7 +907,7 @@ class QtDriver(DriverMixin, QObject):
|
||||
origin_id_ = selected[0]
|
||||
|
||||
pending.append((origin_id_, Path(origin_path)))
|
||||
else:
|
||||
elif (len(selected) > 1) or (len(selected) <= 1):
|
||||
for item in selected:
|
||||
entry = self.lib.get_entry(item)
|
||||
filepath: Path = entry.path
|
||||
@@ -925,30 +924,39 @@ class QtDriver(DriverMixin, QObject):
|
||||
e_id, f = tup
|
||||
if (origin_path == f) or (not origin_path):
|
||||
self.main_window.preview_panel.preview_thumb.media_player.stop()
|
||||
if delete_file(self.lib.library_dir / f):
|
||||
self.main_window.status_bar.showMessage(
|
||||
Translations.format(
|
||||
"status.deleting_file", i=i, count=len(pending), path=f
|
||||
)
|
||||
)
|
||||
self.main_window.status_bar.repaint()
|
||||
self.lib.remove_entries([e_id])
|
||||
|
||||
msg = Translations.format(
|
||||
"status.deleting_file", i=i, count=len(pending), path=f
|
||||
)
|
||||
self.main_window.status_bar.showMessage(msg)
|
||||
self.main_window.status_bar.repaint()
|
||||
|
||||
self.lib.remove_entries([e_id])
|
||||
if delete_file(library_dir / f):
|
||||
deleted_count += 1
|
||||
selected.clear()
|
||||
self.clear_select_action_callback()
|
||||
|
||||
self.clear_select_action_callback()
|
||||
self.update_browsing_state()
|
||||
if deleted_count > 0:
|
||||
self.update_browsing_state()
|
||||
self.main_window.preview_panel.set_selection(selected)
|
||||
|
||||
if deleted_count > 0 and deleted_count != len(pending):
|
||||
msg = Translations.format("status.deleted_partial_warning", count=deleted_count)
|
||||
else:
|
||||
index = min(deleted_count, 2)
|
||||
msg = (
|
||||
Translations["status.deleted_none"],
|
||||
Translations["status.deleted_file_singular"],
|
||||
Translations.format("status.deleted_file_plural", count=deleted_count),
|
||||
)[index]
|
||||
self.main_window.status_bar.showMessage(msg)
|
||||
if len(selected) <= 1 and deleted_count == 0:
|
||||
self.main_window.status_bar.showMessage(Translations["status.deleted_none"])
|
||||
elif len(selected) <= 1 and deleted_count == 1:
|
||||
self.main_window.status_bar.showMessage(
|
||||
Translations.format("status.deleted_file_plural", count=deleted_count)
|
||||
)
|
||||
elif len(selected) > 1 and deleted_count == 0:
|
||||
self.main_window.status_bar.showMessage(Translations["status.deleted_none"])
|
||||
elif len(selected) > 1 and deleted_count < len(selected):
|
||||
self.main_window.status_bar.showMessage(
|
||||
Translations.format("status.deleted_partial_warning", count=deleted_count)
|
||||
)
|
||||
elif len(selected) > 1 and deleted_count == len(selected):
|
||||
self.main_window.status_bar.showMessage(
|
||||
Translations.format("status.deleted_file_plural", count=deleted_count)
|
||||
)
|
||||
self.main_window.status_bar.repaint()
|
||||
|
||||
def delete_file_confirmation(self, count: int, filename: Path | None = None) -> int:
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
"menu.file.open_create_library": "&Abrir/Crear biblioteca",
|
||||
"menu.file.open_library": "Abrir biblioteca",
|
||||
"menu.file.open_recent_library": "Abrir reciente",
|
||||
"menu.file.refresh_directories": "Actualizar directorios",
|
||||
"menu.file.refresh_directories": "&Actualizar directorios",
|
||||
"menu.file.save_backup": "&Guardar copia de seguridad de la biblioteca",
|
||||
"menu.file.save_library": "Guardar biblioteca",
|
||||
"menu.help": "&Ayuda",
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
"drop_import.progress.window_title": "Fájlok importálása",
|
||||
"drop_import.title": "Fájlütközés",
|
||||
"edit.color_manager": "&Színek kezelése",
|
||||
"edit.copy_fields": "Mezők másolása",
|
||||
"edit.copy_fields": "Mezők &másolása",
|
||||
"edit.paste_fields": "Mezők &beillesztése",
|
||||
"edit.tag_manager": "Címkék kezelése",
|
||||
"entries.duplicate.merge": "Egyező elemek &egyesítése",
|
||||
@@ -212,7 +212,7 @@
|
||||
"menu.delete_selected_files_singular": "Fájl {trash_term} &helyezése",
|
||||
"menu.edit": "S&zerkesztés",
|
||||
"menu.edit.ignore_files": "Fájlok és mappák figyelmen kívül hagyása",
|
||||
"menu.edit.manage_tags": "Címkék kezelése",
|
||||
"menu.edit.manage_tags": "&Címkék ke&zelése",
|
||||
"menu.edit.new_tag": "Ú&j címke",
|
||||
"menu.file": "&Fájl",
|
||||
"menu.file.clear_recent_libraries": "&Legutóbbi könyvtárak listájának törlése",
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
"menu.file.open_create_library": "&Apri/Crea Biblioteca",
|
||||
"menu.file.open_library": "Apri Biblioteca",
|
||||
"menu.file.open_recent_library": "Apri Recenti",
|
||||
"menu.file.refresh_directories": "Aggiorna Cartelle",
|
||||
"menu.file.refresh_directories": "&Aggiorna Cartelle",
|
||||
"menu.file.save_backup": "&Salva Backup della Biblioteca",
|
||||
"menu.file.save_library": "Salva Biblioteca",
|
||||
"menu.help": "&Aiuto",
|
||||
|
||||
@@ -195,7 +195,7 @@
|
||||
"menu.edit.new_tag": "Ny &Etikett",
|
||||
"menu.file": "Fil",
|
||||
"menu.file.clear_recent_libraries": "Fjern Nylige",
|
||||
"menu.file.close_library": "Lukk Bibliotek",
|
||||
"menu.file.close_library": "&Lukk Bibliotek",
|
||||
"menu.file.missing_library.message": "Plasseringen til biblioteket \"{library}\" kan ikke finnes.",
|
||||
"menu.file.missing_library.title": "Manglende Bibliotek",
|
||||
"menu.file.new_library": "Nytt Bibliotek",
|
||||
@@ -212,7 +212,7 @@
|
||||
"menu.select": "Velg",
|
||||
"menu.settings": "Innstillinger...",
|
||||
"menu.tools": "Verktøy",
|
||||
"menu.tools.fix_duplicate_files": "Fiks Duplikate Filer",
|
||||
"menu.tools.fix_duplicate_files": "Fiks Duplikate &Filer",
|
||||
"menu.tools.fix_unlinked_entries": "Fiks &Frakoblede Oppføringer",
|
||||
"menu.view": "&Se",
|
||||
"menu.window": "Vindu",
|
||||
|
||||
@@ -181,14 +181,14 @@
|
||||
"menu.edit.new_tag": "Nowy &Tag",
|
||||
"menu.file": "&Plik",
|
||||
"menu.file.clear_recent_libraries": "Wyczyść ostatnie",
|
||||
"menu.file.close_library": "Zamknij bibliotekę",
|
||||
"menu.file.close_library": "&Zamknij bibliotekę",
|
||||
"menu.file.missing_library.message": "Lokalizacja biblioteki \"{library}\" nie została odnaleziona.",
|
||||
"menu.file.missing_library.title": "Brakująca biblioteka",
|
||||
"menu.file.new_library": "Nowa biblioteka",
|
||||
"menu.file.open_create_library": "&Otwórz/Stwórz bibliotekę",
|
||||
"menu.file.open_library": "Otwórz bibliotekę",
|
||||
"menu.file.open_recent_library": "Otwórz ostatnie",
|
||||
"menu.file.refresh_directories": "Odśwież katalogi",
|
||||
"menu.file.refresh_directories": "&Odśwież katalogi",
|
||||
"menu.file.save_backup": "&Zapisz kopię zapasową biblioteki",
|
||||
"menu.file.save_library": "Zapisz bibliotekę",
|
||||
"menu.help": "&Pomoc",
|
||||
|
||||
@@ -181,7 +181,7 @@
|
||||
"menu.file.open_create_library": "&Abrir/Criar Biblioteca",
|
||||
"menu.file.open_library": "Abrir Biblioteca",
|
||||
"menu.file.open_recent_library": "Abrir Recente",
|
||||
"menu.file.refresh_directories": "Atualizar Pastas",
|
||||
"menu.file.refresh_directories": "&Atualizar Pastas",
|
||||
"menu.file.save_backup": "&Gravar Backup da Biblioteca",
|
||||
"menu.file.save_library": "Gravar Biblioteca",
|
||||
"menu.help": "&Ajuda",
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
"menu.file.open_create_library": "&Abrir/Criar Biblioteca",
|
||||
"menu.file.open_library": "Abrir Biblioteca",
|
||||
"menu.file.open_recent_library": "Abrir Recente",
|
||||
"menu.file.refresh_directories": "Atualizar Pastas",
|
||||
"menu.file.refresh_directories": "&Atualizar Pastas",
|
||||
"menu.file.save_backup": "&Salvar Backup da Biblioteca",
|
||||
"menu.file.save_library": "Salvar Biblioteca",
|
||||
"menu.help": "&Ajuda",
|
||||
|
||||
@@ -195,7 +195,7 @@
|
||||
"menu.file.open_create_library": "&Открыть/создать библиотеку",
|
||||
"menu.file.open_library": "Открыть библиотеку",
|
||||
"menu.file.open_recent_library": "Открыть последнюю",
|
||||
"menu.file.refresh_directories": "Обновить папки",
|
||||
"menu.file.refresh_directories": "&Обновить папки",
|
||||
"menu.file.save_backup": "&Сохранить резервную копию библиотеки",
|
||||
"menu.file.save_library": "Сохранить библиотеку",
|
||||
"menu.help": "&Помощь",
|
||||
|
||||
@@ -216,7 +216,7 @@
|
||||
"menu.edit.new_tag": "புதிய & குறிச்சொல்",
|
||||
"menu.file": "கோப்பு (&f)",
|
||||
"menu.file.clear_recent_libraries": "சமீபத்தியதை அழிக்கவும்",
|
||||
"menu.file.close_library": " நூலகம் மூடு",
|
||||
"menu.file.close_library": "& நூலகம் மூடு",
|
||||
"menu.file.missing_library.message": "\"{library}\" நூலகத்தின் இருப்பிடத்தைக் கண்டுபிடிக்க முடியாது.",
|
||||
"menu.file.missing_library.title": "நூலகம் இல்லை",
|
||||
"menu.file.new_library": "புதிய நூலகம்",
|
||||
@@ -225,7 +225,7 @@
|
||||
"menu.file.open_library": "திறந்த நூலகம்",
|
||||
"menu.file.open_recent_library": "அண்மைக் கால திறப்பு",
|
||||
"menu.file.refresh_directories": "கோப்பகத்தை புதுப்பிக்கவும்",
|
||||
"menu.file.save_backup": " நூலக காப்புப்பிரதியை சேமிக்கவும்",
|
||||
"menu.file.save_backup": "& நூலக காப்புப்பிரதியை சேமிக்கவும்",
|
||||
"menu.file.save_library": "நூலகத்தை சேமிக்கவும்",
|
||||
"menu.help": "உதவி (&h)",
|
||||
"menu.help.about": "பற்றி",
|
||||
|
||||
@@ -182,7 +182,7 @@
|
||||
"menu.edit.new_tag": "Yeni &Etiket",
|
||||
"menu.file": "&Dosya",
|
||||
"menu.file.clear_recent_libraries": "Yakın Geçmişi Temizle",
|
||||
"menu.file.close_library": "Kütüphaneyi Kapat",
|
||||
"menu.file.close_library": "Kütüphaneyi &Kapat",
|
||||
"menu.file.new_library": "Yeni Kütüphane",
|
||||
"menu.file.open_create_library": "Kütüphane &Aç/Oluştur",
|
||||
"menu.file.open_library": "Kütüphane Aç",
|
||||
|
||||
Reference in New Issue
Block a user