# Tagger - Centrální Poznámky Projektu > **DŮLEŽITÉ:** Tento soubor obsahuje VŠE co potřebuji vědět o projektu. > Pokud pracuji na Tagger, VŽDY nejdříve přečtu tento soubor! **Poslední aktualizace:** 2025-12-29 **Verze:** 1.0.4 **Status:** Stable, v aktivním vývoji --- ## O projektu **Tagger** je desktopová aplikace pro správu a organizaci souborů pomocí hierarchických tagů (štítků). **Hlavní funkce:** - Rekurzivní procházení složek - Hierarchické tagy (kategorie/název) - Filtrování podle tagů - Přejmenování tagů a kategorií (včetně aktualizace všech souborů) - Metadata uložená v JSON souborech - Automatická detekce rozlišení videí (ffprobe) - Moderní GUI (qBittorrent-style) - Hardlink struktura - vytváření adresářové struktury pomocí hardlinků podle tagů - Tříúrovňový konfigurační systém (globální, složkový, souborový) - CSFD.cz integrace - získávání informací o filmech z české filmové databáze --- ## Struktura projektu ``` Tagger/ ├── Tagger.py # Entry point ├── PROJECT_NOTES.md # ← TENTO SOUBOR - HLAVNÍ ZDROJ PRAVDY ├── CHANGELOG.md # Historie verzí ├── pyproject.toml # Poetry konfigurace ├── poetry.lock # Zamčené verze závislostí ├── .gitignore # Git ignore pravidla │ ├── src/ │ ├── core/ # Jádro aplikace (ŽÁDNÉ UI!) │ │ ├── tag.py # Tag value object (immutable, from_string parser) │ │ ├── tag_manager.py # Správa tagů a kategorií │ │ ├── file.py # File s metadaty │ │ ├── file_manager.py # Správa souborů, filtrování │ │ ├── config.py # Tříúrovňová konfigurace (global, folder, file) │ │ ├── hardlink_manager.py # Správa hardlink struktury │ │ ├── utils.py # list_files() - rekurzivní procházení │ │ ├── media_utils.py # add_video_resolution_tag (ffprobe) │ │ ├── csfd.py # CSFD.cz scraper (fetch_movie, search_movies) │ │ └── constants.py # APP_NAME, VERSION, APP_VIEWPORT │ │ │ └── ui/ │ ├── gui.py # Moderní qBittorrent-style GUI │ └── utils.py # load_icon() - GUI utility pro ikony │ ├── tests/ # 274 testů, 100% core coverage │ ├── __init__.py │ ├── conftest.py # Pytest fixtures │ ├── test_tag.py # 19 testů (včetně Tag.from_string) │ ├── test_tag_manager.py # 55 testů (včetně rename/merge tagů/kategorií) │ ├── test_file.py # 33 testů (včetně CSFD integrace) │ ├── test_file_manager.py # 78 testů (close_folder, rename/merge v souborech) │ ├── test_config.py # 31 testů │ ├── test_hardlink_manager.py # 28 testů │ ├── test_utils.py # 17 testů │ ├── test_media_utils.py # 3 testy (load_icon v src/ui/utils.py) │ └── test_csfd.py # 19 testů │ ├── src/resources/ │ └── images/32/ # Ikony (32x32 PNG) │ ├── 32_unchecked.png │ ├── 32_checked.png │ └── 32_tag.png │ └── data/samples/ # Testovací data ``` --- ## Architektura ### Vrstvová struktura ``` ┌─────────────────────────────────┐ │ Presentation (UI) │ ← gui.py │ - Tkinter GUI │ - NESMÍ obsahovat business logiku │ - Jen zobrazení + interakce │ - NESMÍ importovat přímo z core ├─────────────────────────────────┤ │ Business Logic │ ← FileManager, TagManager, HardlinkManager │ - Správa souborů/tagů │ - Callable z UI │ - Filtrování, validace │ - Callback pattern pro notifikace ├─────────────────────────────────┤ │ Data Layer │ ← File, Tag (models) │ - File, Tag třídy │ - Immutable kde je možné │ - Validation logic │ - __eq__ a __hash__ správně ├─────────────────────────────────┤ │ Persistence │ ← config.py, .!tag soubory │ - JSON soubory │ - UTF-8 encoding VŽDY │ - Config management │ - ensure_ascii=False └─────────────────────────────────┘ ``` ### Tříúrovňový konfigurační systém 1. **Globální config** (`.Tagger.!gtag` vedle Tagger.py) - Geometrie okna, maximalizace - Poslední otevřená složka - Recent folders 2. **Složkový config** (`.Tagger.!ftag` v projekt složce) - Ignore patterns - Custom tagy pro složku - Hardlink nastavení (output_dir, categories) - Rekurzivní skenování 3. **Souborové tagy** (`.filename.!tag`) - Tagy souboru - Datum - Stav (nové, ignorované) ### Klíčová pravidla #### CO DĚLAT: 1. **UI NESMÍ obsahovat business logiku** ```python # ❌ ŠPATNĚ class GUI: def save_file(self): with open(file, 'w') as f: json.dump(data, f) # ✅ SPRÁVNĚ class GUI: def save_file(self): self.filemanager.save_file(file) ``` 2. **Core moduly NESMÍ importovat UI** ```python # V src/core/*.py NIKDY: import tkinter from src.ui import anything ``` 3. **Dependency Injection - předávat dependencies přes konstruktor** ```python class FileManager: def __init__(self, tagmanager: TagManager): self.tagmanager = tagmanager ``` 4. **UTF-8 encoding VŠUDE** ```python with open(file, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=2) ``` 5. **Type hints VŽDY** ```python def filter_files(files: List[File], tags: List[Tag]) -> List[File]: pass ``` #### CO NEDĚLAT: 1. **Globální stav** - NIKDY 2. **Magic numbers** - použít konstanty 3. **Ignorovat exceptions** - vždy logovat nebo ošetřit 4. **Hardcoded paths** - použít Path --- ## Klíčové komponenty ### 1. Tag (immutable value object) ```python class Tag: def __init__(self, category: str, name: str): self.category = category # Nemění se po vytvoření! self.name = name @property def full_path(self) -> str: return f"{self.category}/{self.name}" ``` ### 2. File (reprezentace souboru s metadaty) ```python class File: def __init__(self, file_path: Path, tagmanager=None): self.file_path = file_path self.filename = file_path.name self.metadata_filename = parent / f".{filename}.!tag" self.tags: list[Tag] = [] self.date: str | None = None ``` **Metadata format (.filename.!tag):** ```json { "new": false, "ignored": false, "tags": ["Stav/Nové", "Video/HD"], "date": "2025-12-23" } ``` ### 3. TagManager (správa tagů) ```python class TagManager: def __init__(self): self.tags_by_category = {} # {category: set(Tag)} # Automaticky načte výchozí tagy (Hodnocení, Barva) ``` **Výchozí tagy:** - Hodnocení: 1-5 hvězd (exkluzivní výběr) - Barva: Červená, Modrá, Zelená, Žlutá, Oranžová ### 4. FileManager (správa souborů) ```python class FileManager: def __init__(self, tagmanager: TagManager): self.filelist: list[File] = [] self.tagmanager = tagmanager self.on_files_changed = None # CALLBACK pro UI! self.global_config = load_global_config() self.folder_config = {} ``` ### 5. CSFD Scraper (filmové informace) ```python from src.core.csfd import fetch_movie, search_movies, CSFDMovie # Načtení informací o filmu z URL movie = fetch_movie("https://www.csfd.cz/film/9423-pane-vy-jste-vdova/") print(movie.title) # „Pane, vy jste vdova!" print(movie.year) # 1970 print(movie.rating) # 82 print(movie.genres) # ['Komedie', 'Sci-Fi'] print(movie.directors) # ['Václav Vorlíček'] print(movie.actors) # ['Iva Janžurová', ...] # Vyhledávání filmů results = search_movies("Pelíšky") for m in results: print(m.title, m.csfd_id) ``` **CSFDMovie atributy:** - `title` - název filmu - `url` - CSFD URL - `year` - rok vydání - `genres` - seznam žánrů - `directors` - seznam režisérů - `actors` - seznam herců - `rating` - hodnocení v % - `rating_count` - počet hodnocení - `duration` - délka v minutách - `country` - země původu - `poster_url` - URL plakátu - `plot` - popis děje - `csfd_id` - ID filmu na CSFD **Závislosti:** `requests`, `beautifulsoup4` (instalace: `poetry add requests beautifulsoup4`) ### 6. HardlinkManager (hardlink struktura) ```python class HardlinkManager: def __init__(self, output_dir: Path): self.output_dir = output_dir def create_structure_for_files(files, categories=None) -> (success, fail) def find_obsolete_links(files, categories=None) -> List[(link, source)] def remove_obsolete_links(files, categories=None) -> (count, paths) def sync_structure(files, categories=None) -> (created, c_fail, removed, r_fail) ``` **Příklad struktury:** ``` output/ ├── žánr/ │ ├── Komedie/ │ │ └── film.mkv (hardlink) │ └── Akční/ │ └── film.mkv (hardlink) └── rok/ └── 1988/ └── film.mkv (hardlink) ``` --- ## GUI ### Moderní GUI (gui.py) ``` ┌─────────────────────────────────────────────────────┐ │ 📁 Otevřít │ 🔄 │ 🏷️ │ 📅 🔍 [____] Toolbar ├────────────┬────────────────────────────────────────┤ │ 📂 Štítky │ ☐ Plná │ Třídění: [Název] [▲] │ │ ├─📁 Stav │ ┌──────────────────────────────────┐ │ │ │ ☑ Nové │ │ Název│Datum│Štítky│Velikost │ │ │ │ ☐ OK │ │file1 │2025 │HD │1.2 MB │ │ │ ├─📁 Video│ │file2 │ │4K │15 MB │ │ │ │ ☐ HD │ └──────────────────────────────────┘ │ │ │ ☐ 4K │ │ ├────────────┴───────────────────────────────────────┤ │ Připraven 3 vybráno │ 125 souborů │ └─────────────────────────────────────────────────────┘ ``` **Použít:** `poetry run python Tagger.py` **Funkce:** - Tabulka s 4 sloupci (Název, Datum, Štítky, Velikost) - Toolbar s tlačítky - Keyboard shortcuts (Ctrl+O, Ctrl+T, F5, Del...) - Status bar se 3 sekcemi - Hromadné přiřazování tagů - Hardlink menu (Nástroje → Hardlink) **Keyboard shortcuts:** - `Ctrl+O` - Otevřít složku - `Ctrl+Q` - Ukončit - `Ctrl+T` - Přiřadit tagy - `Ctrl+D` - Nastavit datum - `Ctrl+F` - Focus search - `F5` - Refresh - `Del` - Smazat z indexu --- ## Vývoj ### Setup prostředí ```bash # Poetry environment (VŽDY použij poetry!) poetry install poetry shell # Nebo přímo: poetry run python Tagger.py ``` ### Testy ```bash # Všechny testy (189 testů) poetry run pytest tests/ -v # S coverage poetry run pytest tests/ --cov=src/core --cov-report=html # Konkrétní modul poetry run pytest tests/test_hardlink_manager.py -v # Quick check poetry run pytest tests/ -q ``` **Test coverage:** 100% core modulů --- ## Coding Standards ### Python Style - **PEP 8** s výjimkami: - Max line length: **120** (ne 79) - Indentation: **4 mezery** (ne taby) - **UTF-8** encoding všude - **Type hints** povinné - **Docstrings** pro public API ### Imports Order ```python # 1. Standard library import os import sys from pathlib import Path # 2. Third-party import tkinter as tk from PIL import Image # 3. Local from src.core.file import File from src.core.tag import Tag ``` --- ## Git Workflow ### Branches ``` main/master ← Production (NE commity přímo!) ↑ release ← Release candidate ↑ devel ← Development integration ↑ feature/* ← Feature branches ← VYVÍJÍME TADY ``` ### Commit Messages ``` : [optional body] 🤖 Generated with Claude Code Co-Authored-By: Claude Opus 4.5 ``` **Types:** - `feat:` - Nová funkce - `fix:` - Bug fix - `refactor:` - Refactoring - `test:` - Testy - `docs:` - Dokumentace - `style:` - Formátování - `chore:` - Build, dependencies --- ## Plánované features - [ ] Progress bar pro dlouhé operace - [ ] Undo/Redo mechanismus - [ ] Export do CSV/Excel - [ ] Dark mode theme - [ ] Drag & drop souborů - [ ] Image preview v sidebar - [ ] SQLite fallback pro >10k souborů - [ ] Full-text search ### Nice to have - [ ] Plugin systém - [ ] Web interface (Flask) - [ ] Cloud sync (Dropbox, GDrive) - [ ] Batch rename podle tagů - [ ] Smart folder suggestions --- ## Metriky projektu **Testy:** 274 (všechny ✅) **Test coverage:** 100% core modulů **Python verze:** 3.12+ **Dependencies:** Pillow (PIL), requests, beautifulsoup4 **Vývojové prostředí:** Poetry **Performance:** - ✅ Dobré: <1000 souborů - ⚠️ Přijatelné: 1000-5000 souborů - ❌ Pomalé: >5000 souborů --- ## Debugování ### Časté problémy **1. TreeView tagy se nezobrazují správně po načtení z CSFD** ``` # Opraveno: přidán update_idletasks() po refresh_sidebar() # Pokud stále přetrvává, zkuste F5 nebo znovu otevřít složku ``` **2. "Cannot import ImageTk"** ```bash # Řešení: Použij poetry environment poetry run python Tagger.py ``` **2. "Config file not found"** ```bash # Normální při prvním spuštění # Vytvoří se automaticky .Tagger.!gtag ``` **3. "Metadata corrupted"** ```python # V config.py je graceful degradation # Vrátí default config při chybě ``` --- ## Dokumentace **AKTUÁLNÍ:** - **PROJECT_NOTES.md** - TENTO SOUBOR (single source of truth) - **CHANGELOG.md** - Historie verzí - Docstrings v kódu --- ## Pro AI asistenty (jako Claude) ### Když začínám práci na projektu: 1. **PŘEČTI TENTO SOUBOR CELÝ!** 2. Zkontroluj `git status` 3. Aktivuj poetry environment 4. Spusť testy (`poetry run pytest tests/`) 5. Dodržuj pravidla výše ### Při commitování: 1. Testy prošly (`pytest tests/`) 2. Type hints přidány 3. UTF-8 encoding 4. Žádné TODO/FIXME 5. Commit message formát správný ### Při přidání nové funkce: 1. Testy napsány PŘED implementací (TDD) 2. Dokumentace aktualizována (TENTO SOUBOR!) 3. Architecture decision zdokumentováno (pokud významné) 4. Type hints všude 5. Error handling přidán --- ## Kontakt & Help **Autor:** honza **Repository:** /home/honza/Documents/Tagger **Python:** 3.12+ **OS:** Linux **Pro pomoc:** - Přečti TENTO soubor - Podívej se do testů (`tests/`) - Zkontroluj docstrings v kódu --- **Last updated:** 2025-12-29 **Maintainer:** Claude Opus 4.5 + honza