This commit is contained in:
Muhamed
2025-04-29 15:07:11 +03:00
parent 156d1a4d70
commit 3384cef83a
7 changed files with 2184 additions and 829 deletions
+129 -147
View File
@@ -17,6 +17,7 @@ from packaging import version
import subprocess
import re
import yt_dlp
from ytsage_gui_dialogs import SubtitleSelectionDialog
class VideoInfoMixin:
def setup_video_info_section(self):
@@ -55,9 +56,10 @@ class VideoInfoMixin:
self.views_label = QLabel()
self.date_label = QLabel()
self.duration_label = QLabel()
self.like_count_label = QLabel()
# Style the info labels
for label in [self.channel_label, self.views_label, self.date_label, self.duration_label]:
for label in [self.channel_label, self.views_label, self.date_label, self.duration_label, self.like_count_label]:
label.setStyleSheet("""
QLabel {
color: #cccccc;
@@ -70,115 +72,53 @@ class VideoInfoMixin:
video_info_layout.addWidget(self.title_label)
video_info_layout.addWidget(self.channel_label)
video_info_layout.addWidget(self.views_label)
video_info_layout.addWidget(self.like_count_label)
video_info_layout.addWidget(self.date_label)
video_info_layout.addWidget(self.duration_label)
# Add spacing before subtitle section
video_info_layout.addSpacing(10)
# Create a horizontal layout for subtitle controls
# --- Subtitle Section ---
subtitle_layout = QHBoxLayout()
subtitle_layout.setSpacing(5) # Reduce spacing between elements
subtitle_layout.setSpacing(10)
# Create subtitle button
self.subtitle_check = QPushButton("Download Subtitles")
self.subtitle_check.setFixedHeight(30)
self.subtitle_check.setFixedWidth(150) # Set fixed width
self.subtitle_check.setCheckable(True)
self.subtitle_check.clicked.connect(self.toggle_subtitle_controls)
self.subtitle_check.setStyleSheet("""
# Subtitle selection button
self.subtitle_select_btn = QPushButton("Select Subtitles...") # Renamed & changed text
self.subtitle_select_btn.setFixedHeight(30)
# self.subtitle_select_btn.setFixedWidth(150) # Let it size naturally or adjust as needed
self.subtitle_select_btn.clicked.connect(self.open_subtitle_dialog)
self.subtitle_select_btn.setStyleSheet("""
QPushButton {
background-color: #363636;
border: 2px solid #3d3d3d;
background-color: #1d1e22;
border: 2px solid #1d1e22;
border-radius: 4px;
padding: 5px;
min-height: 30px;
padding: 5px 10px; /* Adjusted padding */
}
QPushButton:checked {
background-color: #ff0000;
border-color: #cc0000;
QPushButton:hover { background-color: #2a2d36; }
/* Optional: Style differently if subtitles ARE selected */
QPushButton[subtitlesSelected="true"] {
border-color: #c90000; /* Indicate selection */
}
/* Style for disabled state */
QPushButton:disabled {
background-color: #3d3d3d;
color: #888888;
border-color: #3d3d3d;
}
""")
subtitle_layout.addWidget(self.subtitle_check)
self.subtitle_select_btn.setProperty("subtitlesSelected", False) # Custom property for styling
subtitle_layout.addWidget(self.subtitle_select_btn)
# Create subtitle combo box
self.subtitle_combo = QComboBox()
self.subtitle_combo.setFixedHeight(30)
self.subtitle_combo.setFixedWidth(200)
self.subtitle_combo.setVisible(False)
self.subtitle_combo.setStyleSheet("""
QComboBox {
background-color: #363636;
border: 2px solid #3d3d3d;
border-radius: 4px;
padding: 5px;
min-height: 30px;
}
""")
subtitle_layout.addWidget(self.subtitle_combo)
# Label to show number of selected subtitles
self.selected_subs_label = QLabel("0 selected")
self.selected_subs_label.setStyleSheet("color: #cccccc; padding-left: 5px;")
subtitle_layout.addWidget(self.selected_subs_label)
# Create merge subtitles checkbox
self.merge_subs_checkbox = QCheckBox("Merge Subtitles")
self.merge_subs_checkbox.setFixedHeight(30)
self.merge_subs_checkbox.setVisible(False)
self.merge_subs_checkbox.setStyleSheet("""
QCheckBox {
color: #ffffff;
padding: 5px;
margin-left: 10px;
}
QCheckBox::indicator {
width: 18px;
height: 18px;
border-radius: 9px;
}
QCheckBox::indicator:unchecked {
border: 2px solid #666666;
background: #2b2b2b;
border-radius: 9px;
}
QCheckBox::indicator:checked {
border: 2px solid #ff0000;
background: #ff0000;
border-radius: 9px;
}
""")
subtitle_layout.addWidget(self.merge_subs_checkbox)
# Add stretch to push everything to the left
subtitle_layout.addStretch()
# Create a second row for the filter input
filter_layout = QHBoxLayout()
filter_layout.setSpacing(5)
# Create subtitle filter input
self.subtitle_filter_input = QLineEdit()
self.subtitle_filter_input.setFixedHeight(30)
self.subtitle_filter_input.setFixedWidth(200)
self.subtitle_filter_input.setPlaceholderText("Filter languages (e.g., en, es)")
self.subtitle_filter_input.textChanged.connect(self.filter_subtitles)
self.subtitle_filter_input.setVisible(False)
self.subtitle_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;
}
""")
filter_layout.addWidget(self.subtitle_filter_input)
filter_layout.addStretch()
# Add both layouts to video info
# Add the subtitle layout to the main video info layout
video_info_layout.addLayout(subtitle_layout)
video_info_layout.addLayout(filter_layout)
# --- End Subtitle Section ---
# Add stretch at the bottom
video_info_layout.addStretch()
@@ -193,11 +133,11 @@ class VideoInfoMixin:
self.playlist_info_label.setStyleSheet("""
QLabel {
font-size: 12px;
color: #ff9900;
color: #ffffff;
padding: 5px 8px;
margin: 0;
background-color: #2b2b2b;
border: 1px solid #3d3d3d;
background-color: #1d1e22;
border: 1px solid #c90000;
border-radius: 4px;
min-height: 30px;
max-height: 30px;
@@ -207,63 +147,109 @@ class VideoInfoMixin:
return self.playlist_info_label
def update_video_info(self, info):
# Format view count with commas
views = int(info.get('view_count', 0))
formatted_views = f"{views:,}"
# Format upload date
upload_date = info.get('upload_date', '')
if upload_date:
date_obj = datetime.strptime(upload_date, '%Y%m%d')
formatted_date = date_obj.strftime('%B %d, %Y')
if hasattr(self, 'is_playlist') and self.is_playlist:
# Playlist Mode: Show playlist title and video count
self.title_label.setText(self.playlist_info.get('title', 'Unknown Playlist'))
num_videos = len(getattr(self, 'playlist_entries', []))
self.duration_label.setText(f"Total Videos: {num_videos}")
# Hide video-specific info
self.channel_label.setText("")
self.views_label.setText("")
self.date_label.setText("")
self.like_count_label.setText("")
self.channel_label.setVisible(False)
self.views_label.setVisible(False)
self.date_label.setVisible(False)
self.like_count_label.setVisible(False)
else:
formatted_date = 'Unknown date'
# Single Video Mode: Show standard video info
# Ensure labels are visible first
self.channel_label.setVisible(True)
self.views_label.setVisible(True)
self.date_label.setVisible(True)
self.like_count_label.setVisible(True)
# Format duration
duration = info.get('duration', 0)
minutes = duration // 60
seconds = duration % 60
duration_str = f"{minutes}:{seconds:02d}"
# Format view count with commas
views = info.get('view_count')
formatted_views = f"{views:,}" if views is not None else 'N/A'
# Update labels
self.title_label.setText(info.get('title', 'Unknown title'))
self.channel_label.setText(f"Channel: {info.get('uploader', 'Unknown channel')}")
self.views_label.setText(f"Views: {formatted_views}")
self.date_label.setText(f"Upload date: {formatted_date}")
self.duration_label.setText(f"Duration: {duration_str}")
# Format like count with commas
likes = info.get('like_count')
formatted_likes = f"{likes:,}" if likes is not None else 'N/A'
# Format upload date
upload_date = info.get('upload_date', '')
if upload_date:
date_obj = datetime.strptime(upload_date, '%Y%m%d')
formatted_date = date_obj.strftime('%B %d, %Y')
else:
formatted_date = 'Unknown date'
# Format duration
duration = info.get('duration', 0)
minutes = duration // 60
seconds = duration % 60
duration_str = f"{minutes}:{seconds:02d}"
# Update labels
self.title_label.setText(info.get('title', 'Unknown title'))
self.channel_label.setText(f"Channel: {info.get('uploader', 'Unknown channel')}")
self.views_label.setText(f"Views: {formatted_views}")
self.like_count_label.setText(f"Likes: {formatted_likes}")
self.date_label.setText(f"Upload date: {formatted_date}")
self.duration_label.setText(f"Duration: {duration_str}")
def toggle_subtitle_controls(self):
is_checked = self.subtitle_check.isChecked()
self.subtitle_combo.setVisible(is_checked)
self.subtitle_filter_input.setVisible(is_checked)
self.merge_subs_checkbox.setVisible(is_checked)
def open_subtitle_dialog(self):
if not hasattr(self, 'available_subtitles') or not hasattr(self, 'available_automatic_subtitles'):
print("Subtitle info not loaded yet.")
return
def update_subtitle_list(self):
self.subtitle_combo.clear()
if not hasattr(self, 'selected_subtitles'):
self.selected_subtitles = []
if not (self.available_subtitles or self.available_automatic_subtitles):
self.subtitle_combo.addItem("No subtitles available")
return
dialog = SubtitleSelectionDialog(
self.available_subtitles,
self.available_automatic_subtitles,
self.selected_subtitles,
self # Parent for the dialog
)
# Add subtitle options
self.subtitle_combo.addItem("Select subtitle language")
# Access the main application window (parent of the mixin's widget)
# to find the merge checkbox
main_window = self # In this context, self should be the YTSageApp instance
if not isinstance(main_window, QMainWindow):
# If the structure is different, this might need adjustment
# Maybe self.parentWidget() or similar depending on how Mixin is used
print("Warning: Cannot find main window to access merge checkbox.")
merge_checkbox = None
else:
merge_checkbox = getattr(main_window, 'merge_subs_checkbox', None)
# Filter and add subtitles
filter_text = self.subtitle_filter_input.text().lower()
# Add manual subtitles
for lang_code, subtitle_info in self.available_subtitles.items():
if not filter_text or filter_text in lang_code.lower():
self.subtitle_combo.addItem(f"{lang_code} - Manual")
if dialog.exec(): # If user clicks OK
self.selected_subtitles = dialog.get_selected_subtitles()
print(f"Selected subtitles: {self.selected_subtitles}")
# Update UI to reflect selection
count = len(self.selected_subtitles)
self.selected_subs_label.setText(f"{count} selected")
self.subtitle_select_btn.setProperty("subtitlesSelected", count > 0)
# Add auto-generated subtitles
for lang_code, subtitle_info in self.available_automatic_subtitles.items():
if not filter_text or filter_text in lang_code.lower():
self.subtitle_combo.addItem(f"{lang_code} - Auto-generated")
# Enable/disable the merge checkbox in the parent window
if merge_checkbox:
# Only enable merge checkbox if we're not in Audio Only mode
is_audio_only = hasattr(main_window, 'audio_button') and main_window.audio_button.isChecked()
# In audio-only mode, we still allow subtitle selection but not merging
should_enable = count > 0 and not is_audio_only
merge_checkbox.setEnabled(should_enable)
else:
print("Warning: merge_subs_checkbox not found on parent window.")
def filter_subtitles(self):
self.subtitle_filter = self.subtitle_filter_input.text()
self.update_subtitle_list()
# 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().polish(self.subtitle_select_btn)
# No else needed for cancel, state remains unchanged
def download_thumbnail(self, url):
try:
@@ -285,10 +271,6 @@ class VideoInfoMixin:
except Exception as e:
print(f"Error loading thumbnail: {str(e)}")
def toggle_save_thumbnail(self):
self.save_thumbnail = self.save_thumbnail_checkbox.isChecked()
print(f"Save thumbnail toggled: {self.save_thumbnail}") # Debug print
def download_thumbnail_file(self, video_url, path):
if not self.save_thumbnail:
return False