2025-12-28 17:44:24 +01:00
|
|
|
# Tagger - Centrální Poznámky Projektu
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
> **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!
|
|
|
|
|
|
2025-12-30 07:54:30 +01:00
|
|
|
**Poslední aktualizace:** 2025-12-29
|
2025-12-28 18:05:27 +01:00
|
|
|
**Verze:** 1.0.4
|
2025-12-28 17:44:24 +01:00
|
|
|
**Status:** Stable, v aktivním vývoji
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
## O projektu
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
**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ů
|
2025-12-30 07:54:30 +01:00
|
|
|
- Přejmenování tagů a kategorií (včetně aktualizace všech souborů)
|
2025-12-23 11:28:05 +01:00
|
|
|
- Metadata uložená v JSON souborech
|
|
|
|
|
- Automatická detekce rozlišení videí (ffprobe)
|
2025-12-28 17:44:24 +01:00
|
|
|
- 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ý)
|
2025-12-30 07:54:30 +01:00
|
|
|
- CSFD.cz integrace - získávání informací o filmech z české filmové databáze
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
## Struktura projektu
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Tagger/
|
2025-12-28 17:44:24 +01:00
|
|
|
├── Tagger.py # Entry point
|
2025-12-23 11:28:05 +01:00
|
|
|
├── PROJECT_NOTES.md # ← TENTO SOUBOR - HLAVNÍ ZDROJ PRAVDY
|
2025-12-28 17:44:24 +01:00
|
|
|
├── CHANGELOG.md # Historie verzí
|
2025-12-23 11:28:05 +01:00
|
|
|
├── pyproject.toml # Poetry konfigurace
|
|
|
|
|
├── poetry.lock # Zamčené verze závislostí
|
|
|
|
|
├── .gitignore # Git ignore pravidla
|
|
|
|
|
│
|
|
|
|
|
├── src/
|
|
|
|
|
│ ├── core/ # Jádro aplikace (ŽÁDNÉ UI!)
|
2025-12-30 07:54:30 +01:00
|
|
|
│ │ ├── tag.py # Tag value object (immutable, from_string parser)
|
2025-12-23 11:28:05 +01:00
|
|
|
│ │ ├── tag_manager.py # Správa tagů a kategorií
|
|
|
|
|
│ │ ├── file.py # File s metadaty
|
|
|
|
|
│ │ ├── file_manager.py # Správa souborů, filtrování
|
2025-12-28 17:44:24 +01:00
|
|
|
│ │ ├── config.py # Tříúrovňová konfigurace (global, folder, file)
|
|
|
|
|
│ │ ├── hardlink_manager.py # Správa hardlink struktury
|
2025-12-23 11:28:05 +01:00
|
|
|
│ │ ├── utils.py # list_files() - rekurzivní procházení
|
2025-12-30 07:54:30 +01:00
|
|
|
│ │ ├── media_utils.py # add_video_resolution_tag (ffprobe)
|
|
|
|
|
│ │ ├── csfd.py # CSFD.cz scraper (fetch_movie, search_movies)
|
|
|
|
|
│ │ └── constants.py # APP_NAME, VERSION, APP_VIEWPORT
|
2025-12-23 11:28:05 +01:00
|
|
|
│ │
|
|
|
|
|
│ └── ui/
|
2025-12-30 07:54:30 +01:00
|
|
|
│ ├── gui.py # Moderní qBittorrent-style GUI
|
|
|
|
|
│ └── utils.py # load_icon() - GUI utility pro ikony
|
2025-12-23 11:28:05 +01:00
|
|
|
│
|
2025-12-30 07:54:30 +01:00
|
|
|
├── tests/ # 274 testů, 100% core coverage
|
2025-12-23 11:28:05 +01:00
|
|
|
│ ├── __init__.py
|
|
|
|
|
│ ├── conftest.py # Pytest fixtures
|
2025-12-30 07:54:30 +01:00
|
|
|
│ ├── 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ů
|
2025-12-28 17:44:24 +01:00
|
|
|
│ ├── test_hardlink_manager.py # 28 testů
|
2025-12-23 11:28:05 +01:00
|
|
|
│ ├── test_utils.py # 17 testů
|
2025-12-30 07:54:30 +01:00
|
|
|
│ ├── test_media_utils.py # 3 testy (load_icon v src/ui/utils.py)
|
|
|
|
|
│ └── test_csfd.py # 19 testů
|
2025-12-23 11:28:05 +01:00
|
|
|
│
|
|
|
|
|
├── src/resources/
|
2025-12-28 17:44:24 +01:00
|
|
|
│ └── images/32/ # Ikony (32x32 PNG)
|
2025-12-23 11:28:05 +01:00
|
|
|
│ ├── 32_unchecked.png
|
|
|
|
|
│ ├── 32_checked.png
|
|
|
|
|
│ └── 32_tag.png
|
|
|
|
|
│
|
2025-12-28 17:44:24 +01:00
|
|
|
└── data/samples/ # Testovací data
|
2025-12-23 11:28:05 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
## Architektura
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
### Vrstvová struktura
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
┌─────────────────────────────────┐
|
2025-12-28 17:44:24 +01:00
|
|
|
│ Presentation (UI) │ ← gui.py
|
2025-12-23 11:28:05 +01:00
|
|
|
│ - Tkinter GUI │ - NESMÍ obsahovat business logiku
|
|
|
|
|
│ - Jen zobrazení + interakce │ - NESMÍ importovat přímo z core
|
|
|
|
|
├─────────────────────────────────┤
|
2025-12-28 17:44:24 +01:00
|
|
|
│ Business Logic │ ← FileManager, TagManager, HardlinkManager
|
2025-12-23 11:28:05 +01:00
|
|
|
│ - 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
|
|
|
|
|
└─────────────────────────────────┘
|
|
|
|
|
```
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
### 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é)
|
|
|
|
|
|
2025-12-23 11:28:05 +01:00
|
|
|
### Klíčová pravidla
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
#### CO DĚLAT:
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
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
|
|
|
|
|
```
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
#### CO NEDĚLAT:
|
2025-12-23 11:28:05 +01:00
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
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
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
## Klíčové komponenty
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
### 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)}
|
2025-12-28 17:44:24 +01:00
|
|
|
# Automaticky načte výchozí tagy (Hodnocení, Barva)
|
2025-12-23 11:28:05 +01:00
|
|
|
```
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
**Výchozí tagy:**
|
|
|
|
|
- Hodnocení: 1-5 hvězd (exkluzivní výběr)
|
|
|
|
|
- Barva: Červená, Modrá, Zelená, Žlutá, Oranžová
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
### 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!
|
2025-12-28 17:44:24 +01:00
|
|
|
self.global_config = load_global_config()
|
|
|
|
|
self.folder_config = {}
|
2025-12-23 11:28:05 +01:00
|
|
|
```
|
|
|
|
|
|
2025-12-30 07:54:30 +01:00
|
|
|
### 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)
|
2025-12-28 17:44:24 +01:00
|
|
|
|
2025-12-23 11:28:05 +01:00
|
|
|
```python
|
2025-12-28 17:44:24 +01:00
|
|
|
class HardlinkManager:
|
|
|
|
|
def __init__(self, output_dir: Path):
|
|
|
|
|
self.output_dir = output_dir
|
2025-12-23 11:28:05 +01:00
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
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)
|
2025-12-23 11:28:05 +01:00
|
|
|
```
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
**Příklad struktury:**
|
2025-12-23 11:28:05 +01:00
|
|
|
```
|
2025-12-28 17:44:24 +01:00
|
|
|
output/
|
|
|
|
|
├── žánr/
|
|
|
|
|
│ ├── Komedie/
|
|
|
|
|
│ │ └── film.mkv (hardlink)
|
|
|
|
|
│ └── Akční/
|
|
|
|
|
│ └── film.mkv (hardlink)
|
|
|
|
|
└── rok/
|
|
|
|
|
└── 1988/
|
|
|
|
|
└── film.mkv (hardlink)
|
2025-12-23 11:28:05 +01:00
|
|
|
```
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
---
|
2025-12-23 11:28:05 +01:00
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
## GUI
|
|
|
|
|
|
|
|
|
|
### Moderní GUI (gui.py)
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
```
|
|
|
|
|
┌─────────────────────────────────────────────────────┐
|
|
|
|
|
│ 📁 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ů │
|
|
|
|
|
└─────────────────────────────────────────────────────┘
|
|
|
|
|
```
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
**Použít:** `poetry run python Tagger.py`
|
2025-12-23 11:28:05 +01:00
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
**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)
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
**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
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
## Vývoj
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
### 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
|
2025-12-28 17:44:24 +01:00
|
|
|
# Všechny testy (189 testů)
|
2025-12-23 11:28:05 +01:00
|
|
|
poetry run pytest tests/ -v
|
|
|
|
|
|
|
|
|
|
# S coverage
|
|
|
|
|
poetry run pytest tests/ --cov=src/core --cov-report=html
|
|
|
|
|
|
|
|
|
|
# Konkrétní modul
|
2025-12-28 17:44:24 +01:00
|
|
|
poetry run pytest tests/test_hardlink_manager.py -v
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
# Quick check
|
|
|
|
|
poetry run pytest tests/ -q
|
|
|
|
|
```
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
**Test coverage:** 100% core modulů
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
## Coding Standards
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
### 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
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
## Git Workflow
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
### Branches
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
main/master ← Production (NE commity přímo!)
|
|
|
|
|
↑
|
|
|
|
|
release ← Release candidate
|
|
|
|
|
↑
|
|
|
|
|
devel ← Development integration
|
|
|
|
|
↑
|
|
|
|
|
feature/* ← Feature branches ← VYVÍJÍME TADY
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Commit Messages
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
<type>: <subject>
|
|
|
|
|
|
|
|
|
|
[optional body]
|
|
|
|
|
|
|
|
|
|
🤖 Generated with Claude Code
|
2025-12-28 17:44:24 +01:00
|
|
|
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
2025-12-23 11:28:05 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Types:**
|
|
|
|
|
- `feat:` - Nová funkce
|
|
|
|
|
- `fix:` - Bug fix
|
|
|
|
|
- `refactor:` - Refactoring
|
|
|
|
|
- `test:` - Testy
|
|
|
|
|
- `docs:` - Dokumentace
|
|
|
|
|
- `style:` - Formátování
|
|
|
|
|
- `chore:` - Build, dependencies
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
## Plánované features
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
- [ ] 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
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
## Metriky projektu
|
2025-12-23 11:28:05 +01:00
|
|
|
|
2025-12-30 07:54:30 +01:00
|
|
|
**Testy:** 274 (všechny ✅)
|
2025-12-23 11:28:05 +01:00
|
|
|
**Test coverage:** 100% core modulů
|
2025-12-28 17:44:24 +01:00
|
|
|
**Python verze:** 3.12+
|
2025-12-30 07:54:30 +01:00
|
|
|
**Dependencies:** Pillow (PIL), requests, beautifulsoup4
|
2025-12-23 11:28:05 +01:00
|
|
|
**Vývojové prostředí:** Poetry
|
|
|
|
|
|
|
|
|
|
**Performance:**
|
|
|
|
|
- ✅ Dobré: <1000 souborů
|
|
|
|
|
- ⚠️ Přijatelné: 1000-5000 souborů
|
|
|
|
|
- ❌ Pomalé: >5000 souborů
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
## Debugování
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
### Časté problémy
|
|
|
|
|
|
2025-12-30 07:54:30 +01:00
|
|
|
**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"**
|
2025-12-23 11:28:05 +01:00
|
|
|
```bash
|
|
|
|
|
# Řešení: Použij poetry environment
|
2025-12-28 17:44:24 +01:00
|
|
|
poetry run python Tagger.py
|
2025-12-23 11:28:05 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**2. "Config file not found"**
|
|
|
|
|
```bash
|
|
|
|
|
# Normální při prvním spuštění
|
2025-12-28 17:44:24 +01:00
|
|
|
# Vytvoří se automaticky .Tagger.!gtag
|
2025-12-23 11:28:05 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**3. "Metadata corrupted"**
|
|
|
|
|
```python
|
|
|
|
|
# V config.py je graceful degradation
|
|
|
|
|
# Vrátí default config při chybě
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
## Dokumentace
|
2025-12-23 11:28:05 +01:00
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
**AKTUÁLNÍ:**
|
|
|
|
|
- **PROJECT_NOTES.md** - TENTO SOUBOR (single source of truth)
|
|
|
|
|
- **CHANGELOG.md** - Historie verzí
|
2025-12-23 11:28:05 +01:00
|
|
|
- Docstrings v kódu
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
## Pro AI asistenty (jako Claude)
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
### Když začínám práci na projektu:
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
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
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
### Při commitování:
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
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ý
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
### Při přidání nové funkce:
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
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
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-28 17:44:24 +01:00
|
|
|
## Kontakt & Help
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
**Autor:** honza
|
2025-12-28 17:44:24 +01:00
|
|
|
**Repository:** /home/honza/Documents/Tagger
|
|
|
|
|
**Python:** 3.12+
|
|
|
|
|
**OS:** Linux
|
2025-12-23 11:28:05 +01:00
|
|
|
|
|
|
|
|
**Pro pomoc:**
|
|
|
|
|
- Přečti TENTO soubor
|
|
|
|
|
- Podívej se do testů (`tests/`)
|
|
|
|
|
- Zkontroluj docstrings v kódu
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-30 07:54:30 +01:00
|
|
|
**Last updated:** 2025-12-29
|
2025-12-28 17:44:24 +01:00
|
|
|
**Maintainer:** Claude Opus 4.5 + honza
|