From ffb938b181c6a8c02e3566648d6177800ec03798 Mon Sep 17 00:00:00 2001 From: oop7 <110548351+oop7@users.noreply.github.com> Date: Sat, 17 Jan 2026 21:43:01 +0200 Subject: [PATCH] Add playlist filter and show video durations in selection dialog Introduces a filter input to the PlaylistSelectionDialog for searching videos by title and displays video durations next to each entry. Updates English translations to support the new filter placeholder and analysis status message. --- languages/en.json | 2 + .../ytsage_dialogs_selection.py | 51 +++++++++++++++++-- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/languages/en.json b/languages/en.json index 0fff390..8f7684b 100644 --- a/languages/en.json +++ b/languages/en.json @@ -92,6 +92,7 @@ "sponsorblock_description": "Select which types of video segments to automatically remove during download.\nSponsorBlock uses community-submitted data to identify these segments.", "select_subtitles": "Select Subtitles", "filter_languages_placeholder": "Filter languages (e.g., en, es)...", + "filter_playlist_placeholder": "Filter videos...", "no_subtitles_available": "No subtitles available", "matching": "matching" }, @@ -336,6 +337,7 @@ "analyzing_updating_table": "Analyzing (95%)... Updating format table", "analysis_complete": "Analysis complete!", "analyzing_extracting_ytdlp": "Analyzing (30%)... Extracting info", + "analyzing_fetching_first_video": "Analyzing... Fetching formats for first video", "analyzing_processing_data": "Analyzing (60%)... Processing data", "analyzing_processing_formats_ytdlp": "Analyzing (75%)... Processing formats", "analyzing_loading_thumbnail_ytdlp": "Analyzing (85%)... Loading thumbnail", diff --git a/src/gui/ytsage_gui_dialogs/ytsage_dialogs_selection.py b/src/gui/ytsage_gui_dialogs/ytsage_dialogs_selection.py index 9d36b6d..bead261 100644 --- a/src/gui/ytsage_gui_dialogs/ytsage_dialogs_selection.py +++ b/src/gui/ytsage_gui_dialogs/ytsage_dialogs_selection.py @@ -208,6 +208,27 @@ class PlaylistSelectionDialog(QDialog): # Main layout main_layout = QVBoxLayout(self) + # Filter Input + self.filter_input = QLineEdit() + self.filter_input.setPlaceholderText(_("dialogs.filter_playlist_placeholder")) + self.filter_input.textChanged.connect(self.filter_list) + self.filter_input.setStyleSheet( + """ + QLineEdit { + background-color: #363636; + border: 2px solid #3d3d3d; + border-radius: 4px; + padding: 5px; + min-height: 30px; + color: white; + } + QLineEdit:focus { + border-color: #ff0000; + } + """ + ) + main_layout.addWidget(self.filter_input) + # Top buttons (Select/Deselect All) button_layout = QHBoxLayout() select_all_btn = QPushButton(_("buttons.select_all")) @@ -339,6 +360,13 @@ class PlaylistSelectionDialog(QDialog): pass # Ignore invalid numbers return selected_indices + def filter_list(self, text: str) -> None: + """Filter the list of checkboxes based on title.""" + text = text.lower() + for checkbox in self.checkboxes: + title = (checkbox.property("full_title") or "").lower() + checkbox.setVisible(text in title) + def _populate_list(self, previously_selected_string) -> None: """Populates the scroll area with checkboxes for each video.""" selected_indices = self._parse_selection_string(previously_selected_string) @@ -356,12 +384,29 @@ class PlaylistSelectionDialog(QDialog): video_index = index + 1 # yt-dlp uses 1-based indexing title = entry.get("title", f"Video {video_index}") - # Shorten title if too long - display_title = (title[:70] + "...") if len(title) > 73 else title + + # Format duration + duration = entry.get("duration") + duration_str = "" + if duration: + try: + m, s = divmod(int(duration), 60) + h, m = divmod(m, 60) + if h > 0: + duration_str = f" [{h}:{m:02d}:{s:02d}]" + else: + duration_str = f" [{m:02d}:{s:02d}]" + except (ValueError, TypeError): + pass + + # Shorten title if too long but keep enough space for duration + max_len = 65 + display_title = (title[:max_len] + "...") if len(title) > max_len + 3 else title - checkbox = QCheckBox(f"{video_index}. {display_title}") + checkbox = QCheckBox(f"{video_index}. {display_title}{duration_str}") checkbox.setChecked(video_index in selected_indices) checkbox.setProperty("video_index", video_index) # Store index + checkbox.setProperty("full_title", title) # Store full title for filtering checkbox.setStyleSheet( """ QCheckBox {