GUI rework to Qt6

This commit is contained in:
2026-01-24 07:50:19 +01:00
parent 47b39aadfe
commit 2bcd5b1f4b
16 changed files with 1613 additions and 1870 deletions

3
src/core/_version.py Normal file
View File

@@ -0,0 +1,3 @@
# Auto-generated version file - do not edit manually
# This file is updated from pyproject.toml when available
VERSION = "1.1.0"

View File

@@ -1,4 +1,106 @@
# src/core/constants.py
VERSION = "v1.0.4"
APP_NAME = "Tagger"
APP_VIEWPORT = "1000x700"
"""
Application constants with dynamic version loading.
Version is loaded from pyproject.toml if available, otherwise from _version.py.
If ENV_DEBUG=true in .env, " DEV" suffix is added to version.
"""
from pathlib import Path
# Paths
_ROOT_DIR = Path(__file__).parent.parent.parent
_PYPROJECT_PATH = _ROOT_DIR / "pyproject.toml"
_VERSION_FILE = Path(__file__).parent / "_version.py"
_ENV_FILE = _ROOT_DIR / ".env"
def _load_env_debug() -> bool:
"""Load ENV_DEBUG from .env file."""
if not _ENV_FILE.exists():
return False
try:
with open(_ENV_FILE, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if line.startswith("ENV_DEBUG="):
value = line.split("=", 1)[1].strip().lower()
return value in ("true", "1", "yes")
except Exception:
pass
return False
def _extract_version_from_toml() -> str | None:
"""Extract version from pyproject.toml."""
if not _PYPROJECT_PATH.exists():
return None
try:
with open(_PYPROJECT_PATH, "r", encoding="utf-8") as f:
content = f.read()
# Simple parsing - find version = "x.x.x" in [project] section
in_project = False
for line in content.split("\n"):
line = line.strip()
if line == "[project]":
in_project = True
elif line.startswith("[") and in_project:
break
elif in_project and line.startswith("version"):
# version = "1.0.4"
if "=" in line:
value = line.split("=", 1)[1].strip().strip('"').strip("'")
return value
except Exception:
pass
return None
def _load_version_from_file() -> str:
"""Load version from _version module."""
try:
from src.core._version import VERSION as _ver
return _ver
except ImportError:
pass
return "0.0.0"
def _save_version_to_file(version: str) -> None:
"""Save version to _version.py for fallback."""
try:
content = f'''# Auto-generated version file - do not edit manually
# This file is updated from pyproject.toml when available
VERSION = "{version}"
'''
with open(_VERSION_FILE, "w", encoding="utf-8") as f:
f.write(content)
except Exception:
pass
def _get_version() -> str:
"""Get version from pyproject.toml or fallback to _version.py."""
# Try to get from pyproject.toml
toml_version = _extract_version_from_toml()
if toml_version:
# Update _version.py for cases when toml is not available
_save_version_to_file(toml_version)
return toml_version
# Fallback to _version.py
return _load_version_from_file()
# Load configuration
DEBUG = _load_env_debug()
VERSION = _get_version()
# Add DEV suffix if debug mode
if DEBUG:
VERSION = f"{VERSION} DEV"
# Application name with version
APP_NAME = f"Tagger v{VERSION}"
# Default window size
APP_VIEWPORT = "1000x700"

View File

@@ -1,6 +1,7 @@
# Module header
import sys
import subprocess
from loguru import logger
from .file import File
from .tag_manager import TagManager
@@ -8,21 +9,13 @@ if __name__ == "__main__":
sys.exit("This module is not intended to be executed as the main program.")
# Backwards compatibility: load_icon moved to src/ui/utils.py
def load_icon(path):
"""Deprecated: Use src.ui.utils.load_icon instead."""
from src.ui.utils import load_icon as _load_icon
return _load_icon(path)
def add_video_resolution_tag(file_obj: File, tagmanager: TagManager):
def add_video_resolution_tag(file_obj: File, tagmanager: TagManager) -> None:
"""
Zjistí vertikální rozlišení videa a přiřadí tag Rozlišení/{výška}p.
Vyžaduje ffprobe (FFmpeg).
Detect video vertical resolution and assign tag Resolution/{height}p.
Requires ffprobe (FFmpeg).
"""
path = str(file_obj.file_path)
try:
# ffprobe vrátí width a height ve formátu JSON
result = subprocess.run(
["ffprobe", "-v", "error", "-select_streams", "v:0",
"-show_entries", "stream=width,height", "-of", "csv=p=0:s=x", path],
@@ -30,13 +23,13 @@ def add_video_resolution_tag(file_obj: File, tagmanager: TagManager):
text=True,
check=True
)
res = result.stdout.strip() # např. "1920x1080"
res = result.stdout.strip() # e.g. "1920x1080"
if "x" not in res:
return
width, height = map(int, res.split("x"))
tag_name = f"Rozlišení/{height}p"
tag_obj = tagmanager.add_tag("Rozlišení", f"{height}p")
file_obj.add_tag(tag_obj)
print(f"Přiřazen tag {tag_name} k {file_obj.filename}")
logger.info("Assigned tag {} to {}", tag_name, file_obj.filename)
except Exception as e:
print(f"Chyba při získávání rozlišení videa {file_obj.filename}: {e}")
logger.error("Failed to get video resolution for {}: {}", file_obj.filename, e)

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +1,22 @@
"""
UI utility functions for Tagger GUI.
UI utility functions for Tagger GUI (PySide6).
"""
from PIL import Image, ImageTk
from pathlib import Path
from PySide6.QtGui import QIcon, QPixmap
def load_icon(path) -> ImageTk.PhotoImage:
def load_icon(path: str | Path, size: int = 16) -> QIcon:
"""
Load an icon from file and resize to 16x16.
Load an icon from file and optionally resize.
Args:
path: Path to the image file
size: Icon size in pixels (default 16)
Returns:
ImageTk.PhotoImage resized to 16x16 pixels
QIcon object
"""
img = Image.open(path)
img = img.resize((16, 16), Image.Resampling.LANCZOS)
return ImageTk.PhotoImage(img)
pixmap = QPixmap(str(path))
if not pixmap.isNull():
pixmap = pixmap.scaled(size, size)
return QIcon(pixmap)