summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/delimiters_category.md43
-rw-r--r--docs/feature_hover_info.md149
-rw-r--r--docs/missing_metadata.md105
-rw-r--r--docs/refactor_settings_ui.md128
-rw-r--r--docs/testing_summary.md32
-rw-r--r--docs/ui_styles.md23
6 files changed, 480 insertions, 0 deletions
diff --git a/docs/delimiters_category.md b/docs/delimiters_category.md
new file mode 100644
index 0000000..0ef148b
--- /dev/null
+++ b/docs/delimiters_category.md
@@ -0,0 +1,43 @@
+# "Delimiters" Category
+
+## Goal
+
+Allow users to customize separators used for artists and album artists, both in metadata and filenames.
+
+## Parameters
+
+- `metadata_delimiter_artist`: artists separator (metadata)
+- `metadata_delimiter_album_artist`: album artists separator (metadata)
+- `filename_delimiter_artist`: artists separator (filename)
+- `filename_delimiter_album_artist`: album artists separator (filename)
+
+## UI
+
+- Page `page_delimiters` inside `sw_categories`
+- GroupBox `gb_delimiters`
+- 4 `QLineEdit` entries (`le_*`) with max width 100px
+
+## Integration
+
+- Add the 4 fields to `DialogPreferences.parameters_line_edit`
+- Load values via `populate_line_edit()`
+- Save via `to_settings()`
+
+## Tests
+
+- `tests/test_delimiters_category.py`: 13 tests
+ - Page existence
+ - Widgets accessibility
+ - Navigation to the page
+ - Width constraints
+
+## Examples
+
+- Semicolon: `"; "` → `Artist1; Artist2`
+- Ampersand: `" & "` → `Artist1 & Artist2`
+- Slash: `" / "` → `Artist1 / Artist2`
+
+## Notes
+
+- Default values are `", "` (comma + space)
+- Fields are kept short (max 100px) to avoid breaking the layout
diff --git a/docs/feature_hover_info.md b/docs/feature_hover_info.md
new file mode 100644
index 0000000..1bc0fc3
--- /dev/null
+++ b/docs/feature_hover_info.md
@@ -0,0 +1,149 @@
+# Hover Info Feature
+
+## Quick Preview on Hover
+
+TIDAL Downloader NG includes a revolutionary hover preview system that displays track metadata instantly when you hover over tracks in the results list.
+
+### Features
+
+- **Instant Display**: Track information appears immediately on hover (no clicks required)
+- **Tabbed Interface**:
+ - **Details Tab**: Shows comprehensive track metadata
+ - **Cover Art Tab**: Displays album artwork
+- **Smart Debouncing**: 350ms delay prevents UI flickering when moving the mouse
+- **Zero Extra API Calls**: Uses pre-loaded track data from search results
+- **Efficient Caching**: Previously viewed tracks display instantly
+
+### Displayed Information
+
+#### Basic Information (Instant)
+
+- **Title**: Track name
+- **Version**: Track version/remix info (if available)
+- **Artists**: Track artists
+- **Track #**: Track number in album
+- **Album**: Album name
+- **Duration**: Track length (mm:ss)
+- **Codec**: Audio quality (LOSSLESS, AAC, etc.)
+- **Bitrate**: Audio bitrate (or N/A for variable bitrate)
+- **Release Date**: Album release date
+- **Popularity**: Track popularity score
+- **ISRC**: International Standard Recording Code
+
+#### Enhanced Information (Async)
+
+- **BPM**: Beats per minute ⏳ (loaded asynchronously from API)
+ - Shows `⏳ Loading...` while fetching (~100-500ms)
+ - Displays actual BPM value when available
+ - Shows `—` if not available
+
+### Cover Art Display
+
+- **Automatic Loading**: Album covers are loaded in the background
+- **Smart Caching**: Covers are cached for instant display on re-hover
+- **Preloading**: First 50 tracks in playlists are preloaded for better UX
+- **Fallback**: Default album image shown if cover is unavailable
+
+### Technical Details
+
+#### Architecture
+
+```
+User hovers over track
+ ↓
+HoverManager detects hover (debounced 350ms)
+ ↓
+InfoTabWidget receives update signal
+ ↓
+_populate_track_details() displays basic info instantly
+ ↓
+_request_track_extras_if_needed() triggers async fetch
+ ↓
+Worker thread fetches BPM from TIDAL API
+ ↓
+Qt Signal invokes callback in main thread
+ ↓
+_update_extras_ui() updates BPM label
+```
+
+#### Performance Optimizations
+
+1. **LRU Cache**: 256-entry cache for track extras
+2. **Cover Cache**: 100-entry cache for album covers
+3. **Thread-Safe**: All background operations are thread-safe
+4. **Event Filtering**: Precise hover detection on tree view viewport
+5. **Graceful Degradation**: Handles missing metadata gracefully
+
+### User Experience
+
+#### On First Hover
+
+```
+Title: Fortuna ✅ Instant
+Artists: Asco ✅ Instant
+Duration: 03:40 ✅ Instant
+Codec: LOSSLESS ✅ Instant
+BPM: ⏳ Loading... ⏱️ Loading indicator (~200ms)
+ ↓
+BPM: 136 ✅ Loaded!
+```
+
+#### On Subsequent Hover (Same Track)
+
+```
+Title: Fortuna ✅ Instant
+Artists: Asco ✅ Instant
+Duration: 03:40 ✅ Instant
+BPM: 136 ✅ Instant (from cache)
+```
+
+### Limitations
+
+Due to TIDAL API limitations, the following fields are **not applicable** in this hover view (they are generally not provided by the public API and thus not displayed):
+
+- ❌ Genres
+- ❌ Label
+- ❌ Producers
+- ❌ Composers
+
+See [missing_metadata.md](missing_metadata.md) for detailed information about API limitations.
+
+### Code Components
+
+- **`InfoTabWidget`**: Main widget for displaying track information
+- **`HoverManager`**: Manages hover events on tree view
+- **`CoverManager`**: Handles cover art loading and caching
+- **`TrackInfoFormatter`**: Formats track metadata for display
+- **`TrackExtrasCache`**: LRU cache for async-loaded metadata
+
+### Configuration
+
+The hover delay is configurable in the code:
+
+```python
+# In hover_manager.py
+self.hover_delay = 350 # milliseconds
+```
+
+Lower values = more responsive but may flicker
+Higher values = more stable but less responsive
+
+### Troubleshooting
+
+**BPM not displaying?**
+
+- Check console for API errors
+- Verify track has BPM in TIDAL (not all tracks do)
+- Cache may have stale data (restart application)
+
+**Cover not loading?**
+
+- Check network connection
+- Some tracks may not have cover art
+- Default image will be shown as fallback
+
+**Hover not working?**
+
+- Ensure you're hovering over the results tree view
+- Check that the application has focus
+- Debounce delay may need adjustment
diff --git a/docs/missing_metadata.md b/docs/missing_metadata.md
new file mode 100644
index 0000000..1bbeec3
--- /dev/null
+++ b/docs/missing_metadata.md
@@ -0,0 +1,105 @@
+# Missing Metadata in the Interface
+
+## Why do some fields display "—" or "N/A"?
+
+When using TIDAL Downloader NG, some metadata fields may display `—` (dash) or `N/A`. This means that **the data is not provided by the TIDAL API** for that specific track/album.
+
+### Affected Fields
+
+The following fields depend on data availability from the TIDAL API:
+
+| Field | API Source | Notes | Status |
+| ------------- | ------------------------------------------------------------------- | -------------------------------------- | ------------------------- |
+| **BPM** | Track JSON (`bpm`) | Loaded asynchronously from API | ✅ Functional |
+| **Bitrate** | Calculated based on codec | `N/A` for LOSSLESS (variable bitrate) | ✅ Functional |
+| **Codec** | Track metadata | Always available (LOSSLESS, AAC, etc.) | ✅ Functional |
+| **Genres** | Album JSON (`genres` or `genre`) | Not available via TIDAL API v2 | ❌ Removed from interface |
+| **Label** | Album JSON (`label` or `recordLabel`) | Not reliably available | ❌ Removed from interface |
+| **Producers** | Track/Album JSON (`credits` or `contributors` with role="producer") | Not available via TIDAL API v2 | ❌ Removed from interface |
+| **Composers** | Track/Album JSON (`credits` or `contributors` with role="composer") | Not available via TIDAL API v2 | ❌ Removed from interface |
+
+### Recent Improvements & API Limitations
+
+**Current version**: The application retrieves available metadata from the TIDAL API:
+
+- ✅ **BPM**: Loaded asynchronously from `track._data['bpm']` via API
+- ✅ Display of basic information: title, artists, album, duration, codec, bitrate
+- ✅ ISRC, track number, release date, popularity
+- ❌ **Genres, Label, Producers, Composers**: Removed from interface (not available via API)
+
+**TIDAL API Limitations**:
+
+According to the official TIDAL OpenAPI specification analysis (https://tidal-music.github.io/tidal-api-reference/):
+
+- ❌ **No reliable `genres` field** in API v2 (sometimes present but often empty)
+- ❌ **No `credits` field** in API v2
+- ❌ **No `contributors` field** in API v2
+- ❌ **No `producers` field** available
+- ❌ **No `composers` field** available
+- ❌ **`label` and `recordLabel`** only available at album level, and often absent
+
+The TIDAL API v2 (official JSON:API) does **NOT** reliably provide these metadata. The older API v1 (undocumented) may contain some of these fields randomly, but they are not guaranteed and depend entirely on what music labels provide to TIDAL.
+
+### What is Actually Available
+
+Fields **guaranteed** by the TIDAL API:
+
+- ✅ `title`, `duration`, `isrc`, `explicit`
+- ✅ `bpm` (optional, when provided by the label)
+- ✅ `popularity` (0.0 - 1.0)
+- ✅ `mediaTags` (HIRES_LOSSLESS, etc.)
+- ✅ `artists` via relationship
+- ✅ `album` via relationship
+- ✅ `genres` via relationship (but often empty)
+
+### Why is this Data Missing?
+
+1. **TIDAL doesn't have the information**: Some metadata is not provided by music labels
+2. **Data not exposed by API**: Even if TIDAL displays certain information on their website, the public API may not provide it
+3. **Variability by track**: An album may have genres, but individual tracks may not
+4. **Metadata quality**: Some independent or older tracks may have incomplete metadata
+
+### API Response Example
+
+For the track "Breathing (Techno)" in your screenshot:
+
+```
+Track ID: 336084531
+- BPM: Not provided by TIDAL
+- Label: Not provided by TIDAL
+- Genres: Not provided by TIDAL
+- Contributors: Maybe available but without specific role (producer/composer)
+```
+
+### How to Get More Data?
+
+1. **Check TIDAL directly**: Sometimes data is visible on the TIDAL website but not via API
+2. **Use other sources**: MusicBrainz, Discogs, etc. (not integrated in tidal-dl-ng)
+3. **Manual editing**: After download, use a tag editor (Mp3tag, Kid3, etc.)
+
+### Debugging
+
+To see what the TIDAL API returns, you can check the console output when hovering over tracks. The application silently fetches BPM data in the background without cluttering the console.
+
+**Technical Architecture**: BPM is loaded asynchronously:
+
+1. Worker thread fetches raw JSON data from TIDAL API
+2. `parse_track_and_album_extras()` extracts BPM from JSON
+3. Qt Signal (`s_invoke_callback`) emits result to main thread
+4. Stored callback is invoked in main thread (safe for UI updates)
+5. `_handle_track_extras_ready` verifies it's the correct track
+6. `_update_extras_ui` updates the BPM label in the interface
+
+**Loading Indicator**: While BPM is being fetched, you'll see:
+
+- `⏳ Loading...` - BPM data is being fetched from API (~100-500ms)
+- `136` - BPM value successfully loaded
+- `—` - BPM not available for this track
+
+**Note**: If you previously hovered over a track, the BPM will display instantly on subsequent hovers thanks to the built-in cache system.
+
+## Bitrate = N/A for LOSSLESS
+
+The **LOSSLESS** codec (FLAC) uses lossless compression with a **variable bitrate (VBR)**. The exact bitrate depends on the audio content and changes constantly during playback. This is why it is displayed as `N/A` rather than a fixed number.
+
+For codecs with fixed bitrate (AAC, etc.), you will see a number like "320 kbps".
diff --git a/docs/refactor_settings_ui.md b/docs/refactor_settings_ui.md
new file mode 100644
index 0000000..651427c
--- /dev/null
+++ b/docs/refactor_settings_ui.md
@@ -0,0 +1,128 @@
+# Settings Window Refactor
+
+Date: 2025-11-30
+Author: Automation (Copilot)
+
+## Goal
+
+Refactor the settings window to improve usability and maintainability:
+
+- Category list on the left
+- Settings content on the right via QStackedWidget
+- Clear separation of pages (Flags, Quality, Numbers, Paths & Formats, Delimiters)
+- Consistent dark styling and tuned spacing
+- Add unit and integration tests (61 total)
+
+## Key Changes
+
+### 1. UI Architecture
+
+- Navigation column: `QListWidget (lw_categories)`
+- Pages container: `QStackedWidget (sw_categories)`
+- Pages created:
+ - `page_flags` (GroupBox: gb_flags)
+ - `page_quality` (GroupBox: gb_choices)
+ - `page_numbers` (GroupBox: gb_numbers)
+ - `page_paths` (GroupBox: gb_path)
+ - `page_delimiters` (GroupBox: gb_delimiters) — NEW
+
+Impacted file: `tidal_dl_ng/ui/dialog_settings.ui` (auto-generated `dialog_settings.py`).
+
+### 2. New Category: Delimiters
+
+- "Delimiters" page with 4 `QLineEdit` fields to edit separators:
+ - `metadata_delimiter_artist`
+ - `metadata_delimiter_album_artist`
+ - `filename_delimiter_artist`
+ - `filename_delimiter_album_artist`
+- Automatic integration with `DialogPreferences` through `parameters_line_edit`, `populate_line_edit()` and `to_settings()`.
+
+Files touched:
+
+- `tidal_dl_ng/ui/dialog_settings.ui` (new page)
+- `tidal_dl_ng/ui/dialog_settings.py` (regenerated)
+- `tidal_dl_ng/dialog.py` (added 4 parameters and new category in `_init_categories`).
+
+### 3. Styles & Spacing
+
+- Category list: dark style, blue selection, gray hover, light text.
+- Vertical spacing: list item margin `2px 0px` (and optional view spacing).
+- Settings area: dark background (QStackedWidget), styled GroupBoxes.
+
+Files touched:
+
+- `tidal_dl_ng/ui/dialog_settings.ui` (stylesheets on lw_categories and sw_categories)
+- `tidal_dl_ng/ui/dialog_settings.py` (regenerated).
+
+### 4. Tests
+
+- New files:
+ - `tests/test_settings_ui.py`: UI and basic integration (14)
+ - `tests/test_settings_dialog_structure.py`: detailed structure (20)
+ - `tests/test_dialog_preferences_integration.py`: DialogPreferences integration (14)
+ - `tests/test_delimiters_category.py`: Delimiters page (13)
+- Total: **61 tests**; ruff/black/pyupgrade applied via pre-commit.
+
+### 5. Pre-commit & Quality
+
+- Ruff fixes:
+ - F841 (unused variable) in `test_dialog_preferences_integration.py`
+ - S108 (using /tmp) replaced by `Path.home()` and safe values
+- end-of-file-fixer and black reformatted automatically.
+
+## Usage
+
+### Launch the UI
+
+- Via the app: `poetry run tidal-dl-ng-gui` (or `python -m tidal_dl_ng.gui`)
+
+### Navigate
+
+- Select a category in `lw_categories`
+- The corresponding page shows in `sw_categories`.
+
+### Edit separators
+
+- Open the "Delimiters" category
+- Edit fields `le_metadata_delimiter_*` and `le_filename_delimiter_*`
+- Confirm via OK
+
+## Known issue: poetry+dulwich KeyError b'HEAD
+
+- Cause: dulwich cannot resolve HEAD in the Git repo when Poetry queries VCS info.
+- Fix: ensure `.git/HEAD` points to an existing branch (e.g. `ref: refs/heads/main`) and the branch exists; then re-run `poetry install`. See commands below.
+
+## Useful Commands (PowerShell)
+
+```powershell
+cd C:\Users\mathe\PycharmProjects\tidal-dl-ng
+poetry check --lock
+poetry run pre-commit run -a
+pytest -q
+```
+
+To fix HEAD if needed:
+
+```powershell
+cd C:\Users\mathe\PycharmProjects\tidal-dl-ng
+Get-Content .git\HEAD
+# If empty/incorrect:
+git init
+git add .
+git commit -m "Initialize repo for Poetry/Dulwich"
+git branch -M main
+Get-Content .git\HEAD
+poetry install -vvv --no-interaction --all-extras --with dev,docs
+```
+
+## Impact
+
+- Better UX: category navigation, improved readability
+- Extensible: easy to add new pages/settings
+- Quality: comprehensive tests ensure robustness
+
+## Next Steps
+
+- Add contextual help (tooltips) for new delimiter fields
+- Optionally adjust list spacing (8–10) based on feedback
+- Add a preview of resulting formatting (e.g., sample metadata)
diff --git a/docs/testing_summary.md b/docs/testing_summary.md
new file mode 100644
index 0000000..5229548
--- /dev/null
+++ b/docs/testing_summary.md
@@ -0,0 +1,32 @@
+# Created Tests and Results
+
+## Test files
+
+- `tests/test_settings_ui.py` (14 tests)
+- `tests/test_settings_dialog_structure.py` (20 tests)
+- `tests/test_dialog_preferences_integration.py` (14 tests)
+- `tests/test_delimiters_category.py` (13 tests)
+
+## Total
+
+- **61 tests** (unit + integration)
+
+## Coverage
+
+- UI creation and structure
+- Category navigation
+- Widgets presence and accessibility
+- New "Delimiters" page
+- Quality: ruff/black/pyupgrade enforced by pre-commit
+
+## Commands
+
+```powershell
+cd C:\Users\mathe\PycharmProjects\tidal-dl-ng
+poetry run pre-commit run -a
+pytest -q
+```
+
+## Note
+
+If `poetry install` fails with KeyError b'HEAD, see "Settings Window Refactor" doc to fix the Git repo’s HEAD.
diff --git a/docs/ui_styles.md b/docs/ui_styles.md
new file mode 100644
index 0000000..6e2a81e
--- /dev/null
+++ b/docs/ui_styles.md
@@ -0,0 +1,23 @@
+# UI Styles (Dark)
+
+## Category List (QListWidget)
+
+- Background: `#2b2b2b`
+- Selection: blue `#3d5a80` + white text
+- Hover: gray `#3a3a3a`
+- Text: light gray `#e0e0e0`
+- Padding: 4px
+- Item margin: 2px vertical
+- View spacing: 0 (can be set to 6–10 for more breathing room)
+
+## Settings Area (QStackedWidget)
+
+- Background: `#333333`
+- Border: `#3d3d3d`
+- GroupBox: background `#3a3a3a`, border `#4a4a4a`, radius 6
+
+## Tuning Tips
+
+- Increase view spacing to 8–10 if preferred visually
+- Harmonize corner radius with global UI style
+- Use tooltips to explain parameters