Add SponsorBlock category selection to video info UI
Introduces a SponsorBlock section to the video info UI, allowing users to select categories via a dialog. Refactors print statements to use the logger for consistency. Updates imports and improves UI feedback for subtitle and SponsorBlock selections.
This commit is contained in:
@@ -16,13 +16,14 @@ from pathlib import Path
|
|||||||
from packaging import version
|
from packaging import version
|
||||||
import subprocess
|
import subprocess
|
||||||
import re
|
import re
|
||||||
|
from ..core.ytsage_logging import logger
|
||||||
try:
|
try:
|
||||||
import yt_dlp
|
import yt_dlp
|
||||||
YT_DLP_AVAILABLE = True
|
YT_DLP_AVAILABLE = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
YT_DLP_AVAILABLE = False
|
YT_DLP_AVAILABLE = False
|
||||||
print("Warning: yt-dlp not available at startup, will be downloaded at runtime")
|
logger.warning("yt-dlp not available at startup, will be downloaded at runtime")
|
||||||
from ytsage_gui_dialogs import SubtitleSelectionDialog
|
from .ytsage_gui_dialogs import SubtitleSelectionDialog, SponsorBlockCategoryDialog
|
||||||
|
|
||||||
class VideoInfoMixin:
|
class VideoInfoMixin:
|
||||||
def setup_video_info_section(self):
|
def setup_video_info_section(self):
|
||||||
@@ -124,6 +125,53 @@ class VideoInfoMixin:
|
|||||||
video_info_layout.addLayout(subtitle_layout)
|
video_info_layout.addLayout(subtitle_layout)
|
||||||
# --- End Subtitle Section ---
|
# --- End Subtitle Section ---
|
||||||
|
|
||||||
|
# Add small spacing between subtitle and sponsorblock sections
|
||||||
|
video_info_layout.addSpacing(4)
|
||||||
|
|
||||||
|
# --- SponsorBlock Section ---
|
||||||
|
sponsorblock_layout = QHBoxLayout()
|
||||||
|
|
||||||
|
self.sponsorblock_select_btn = QPushButton("SponsorBlock Categories...")
|
||||||
|
self.sponsorblock_select_btn.setFixedHeight(30)
|
||||||
|
self.sponsorblock_select_btn.clicked.connect(self.open_sponsorblock_dialog)
|
||||||
|
self.sponsorblock_select_btn.setStyleSheet("""
|
||||||
|
QPushButton {
|
||||||
|
background-color: #1d1e22;
|
||||||
|
border: 2px solid #1d1e22;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
|
QPushButton:hover {
|
||||||
|
background-color: #2a2d36;
|
||||||
|
}
|
||||||
|
QPushButton[sponsorBlockSelected="true"] {
|
||||||
|
border-color: #c90000;
|
||||||
|
}
|
||||||
|
QPushButton:disabled {
|
||||||
|
background-color: #3d3d3d;
|
||||||
|
color: #888888;
|
||||||
|
border-color: #3d3d3d;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
self.sponsorblock_select_btn.setProperty("sponsorBlockSelected", False)
|
||||||
|
self.sponsorblock_select_btn.setProperty("sponsorBlockSelected", False)
|
||||||
|
sponsorblock_layout.addWidget(self.sponsorblock_select_btn)
|
||||||
|
|
||||||
|
# Label to show selection count
|
||||||
|
self.selected_sponsorblock_label = QLabel("0 selected")
|
||||||
|
self.selected_sponsorblock_label.setStyleSheet("color: #cccccc; padding-left: 5px;")
|
||||||
|
sponsorblock_layout.addWidget(self.selected_sponsorblock_label)
|
||||||
|
|
||||||
|
sponsorblock_layout.addStretch()
|
||||||
|
|
||||||
|
# Add the sponsorblock layout to the main video info layout
|
||||||
|
video_info_layout.addLayout(sponsorblock_layout)
|
||||||
|
# --- End SponsorBlock Section ---
|
||||||
|
|
||||||
|
# Initialize SponsorBlock categories as empty initially (will be set to defaults when user opens dialog)
|
||||||
|
self.selected_sponsorblock_categories = []
|
||||||
|
self._update_sponsorblock_display()
|
||||||
|
|
||||||
# Add stretch at the bottom
|
# Add stretch at the bottom
|
||||||
video_info_layout.addStretch()
|
video_info_layout.addStretch()
|
||||||
|
|
||||||
@@ -208,7 +256,7 @@ class VideoInfoMixin:
|
|||||||
|
|
||||||
def open_subtitle_dialog(self):
|
def open_subtitle_dialog(self):
|
||||||
if not hasattr(self, 'available_subtitles') or not hasattr(self, 'available_automatic_subtitles'):
|
if not hasattr(self, 'available_subtitles') or not hasattr(self, 'available_automatic_subtitles'):
|
||||||
print("Subtitle info not loaded yet.")
|
logger.warning("Subtitle info not loaded yet.")
|
||||||
return
|
return
|
||||||
|
|
||||||
if not hasattr(self, 'selected_subtitles'):
|
if not hasattr(self, 'selected_subtitles'):
|
||||||
@@ -227,7 +275,7 @@ class VideoInfoMixin:
|
|||||||
if not isinstance(main_window, QMainWindow):
|
if not isinstance(main_window, QMainWindow):
|
||||||
# If the structure is different, this might need adjustment
|
# If the structure is different, this might need adjustment
|
||||||
# Maybe self.parentWidget() or similar depending on how Mixin is used
|
# Maybe self.parentWidget() or similar depending on how Mixin is used
|
||||||
print("Warning: Cannot find main window to access merge checkbox.")
|
logger.warning("Cannot find main window to access merge checkbox.")
|
||||||
merge_checkbox = None
|
merge_checkbox = None
|
||||||
else:
|
else:
|
||||||
merge_checkbox = getattr(main_window, 'merge_subs_checkbox', None)
|
merge_checkbox = getattr(main_window, 'merge_subs_checkbox', None)
|
||||||
@@ -235,7 +283,7 @@ class VideoInfoMixin:
|
|||||||
|
|
||||||
if dialog.exec(): # If user clicks OK
|
if dialog.exec(): # If user clicks OK
|
||||||
self.selected_subtitles = dialog.get_selected_subtitles()
|
self.selected_subtitles = dialog.get_selected_subtitles()
|
||||||
print(f"Selected subtitles: {self.selected_subtitles}")
|
logger.info(f"Selected subtitles: {self.selected_subtitles}")
|
||||||
# Update UI to reflect selection
|
# Update UI to reflect selection
|
||||||
count = len(self.selected_subtitles)
|
count = len(self.selected_subtitles)
|
||||||
self.selected_subs_label.setText(f"{count} selected")
|
self.selected_subs_label.setText(f"{count} selected")
|
||||||
@@ -249,13 +297,51 @@ class VideoInfoMixin:
|
|||||||
should_enable = count > 0 and not is_audio_only
|
should_enable = count > 0 and not is_audio_only
|
||||||
merge_checkbox.setEnabled(should_enable)
|
merge_checkbox.setEnabled(should_enable)
|
||||||
else:
|
else:
|
||||||
print("Warning: merge_subs_checkbox not found on parent window.")
|
logger.warning("merge_subs_checkbox not found on parent window.")
|
||||||
|
|
||||||
# Re-apply stylesheet to update button border if property changed
|
# Re-apply stylesheet to update button border if property changed
|
||||||
self.subtitle_select_btn.style().unpolish(self.subtitle_select_btn)
|
self.subtitle_select_btn.style().unpolish(self.subtitle_select_btn)
|
||||||
self.subtitle_select_btn.style().polish(self.subtitle_select_btn)
|
self.subtitle_select_btn.style().polish(self.subtitle_select_btn)
|
||||||
# No else needed for cancel, state remains unchanged
|
# No else needed for cancel, state remains unchanged
|
||||||
|
|
||||||
|
def open_sponsorblock_dialog(self):
|
||||||
|
"""Open the SponsorBlock category selection dialog."""
|
||||||
|
# Initialize selected categories if not exists or empty (first time opening)
|
||||||
|
if not hasattr(self, 'selected_sponsorblock_categories') or not self.selected_sponsorblock_categories:
|
||||||
|
# Use None to let the dialog set its own defaults
|
||||||
|
dialog_categories = None
|
||||||
|
else:
|
||||||
|
dialog_categories = self.selected_sponsorblock_categories
|
||||||
|
|
||||||
|
dialog = SponsorBlockCategoryDialog(dialog_categories, self)
|
||||||
|
|
||||||
|
if dialog.exec():
|
||||||
|
self.selected_sponsorblock_categories = dialog.get_selected_categories()
|
||||||
|
logger.info(f"SponsorBlock categories selected: {self.selected_sponsorblock_categories}")
|
||||||
|
self._update_sponsorblock_display()
|
||||||
|
|
||||||
|
def _update_sponsorblock_display(self):
|
||||||
|
"""Update the SponsorBlock button and label to reflect current selection."""
|
||||||
|
if not hasattr(self, 'selected_sponsorblock_categories'):
|
||||||
|
self.selected_sponsorblock_categories = []
|
||||||
|
|
||||||
|
count = len(self.selected_sponsorblock_categories)
|
||||||
|
|
||||||
|
# Update label text
|
||||||
|
if count == 0:
|
||||||
|
self.selected_sponsorblock_label.setText("0 selected")
|
||||||
|
elif count == 1:
|
||||||
|
self.selected_sponsorblock_label.setText("1 category selected")
|
||||||
|
else:
|
||||||
|
self.selected_sponsorblock_label.setText(f"{count} categories selected")
|
||||||
|
|
||||||
|
# Update button property for styling
|
||||||
|
self.sponsorblock_select_btn.setProperty("sponsorBlockSelected", count > 0)
|
||||||
|
|
||||||
|
# Force style refresh
|
||||||
|
self.sponsorblock_select_btn.style().unpolish(self.sponsorblock_select_btn)
|
||||||
|
self.sponsorblock_select_btn.style().polish(self.sponsorblock_select_btn)
|
||||||
|
|
||||||
def download_thumbnail(self, url):
|
def download_thumbnail(self, url):
|
||||||
try:
|
try:
|
||||||
# Store both thumbnail URL and video URL
|
# Store both thumbnail URL and video URL
|
||||||
@@ -274,7 +360,7 @@ class VideoInfoMixin:
|
|||||||
pixmap.loadFromData(img_byte_arr.getvalue())
|
pixmap.loadFromData(img_byte_arr.getvalue())
|
||||||
self.thumbnail_label.setPixmap(pixmap)
|
self.thumbnail_label.setPixmap(pixmap)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error loading thumbnail: {str(e)}")
|
logger.error(f"Error loading thumbnail: {str(e)}")
|
||||||
|
|
||||||
def download_thumbnail_file(self, video_url, path):
|
def download_thumbnail_file(self, video_url, path):
|
||||||
if not self.save_thumbnail:
|
if not self.save_thumbnail:
|
||||||
@@ -284,7 +370,7 @@ class VideoInfoMixin:
|
|||||||
from yt_dlp import YoutubeDL
|
from yt_dlp import YoutubeDL
|
||||||
import requests # Use requests instead of urlopen
|
import requests # Use requests instead of urlopen
|
||||||
|
|
||||||
print(f"Attempting to save thumbnail for URL: {video_url}")
|
logger.debug(f"Attempting to save thumbnail for URL: {video_url}")
|
||||||
|
|
||||||
ydl_opts = {
|
ydl_opts = {
|
||||||
'quiet': True,
|
'quiet': True,
|
||||||
@@ -323,13 +409,13 @@ class VideoInfoMixin:
|
|||||||
with open(thumbnail_path, 'wb') as f:
|
with open(thumbnail_path, 'wb') as f:
|
||||||
f.write(response.content)
|
f.write(response.content)
|
||||||
|
|
||||||
print(f"Thumbnail saved to: {thumbnail_path}")
|
logger.info(f"Thumbnail saved to: {thumbnail_path}")
|
||||||
self.signals.update_status.emit(f"✅ Thumbnail saved: {filename}")
|
self.signals.update_status.emit(f"✅ Thumbnail saved: {filename}")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error_msg = f"❌ Thumbnail error: {str(e)}"
|
error_msg = f"❌ Thumbnail error: {str(e)}"
|
||||||
print(f"Thumbnail Save Error: {str(e)}")
|
logger.error(f"Thumbnail Save Error: {str(e)}")
|
||||||
self.signals.update_status.emit(error_msg)
|
self.signals.update_status.emit(error_msg)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
Reference in New Issue
Block a user