Add Custom Options & Trim Video
This commit is contained in:
+135
-84
@@ -25,7 +25,7 @@ from ytsage_utils import check_ffmpeg, get_yt_dlp_path, load_saved_path, save_pa
|
|||||||
from ytsage_gui_dialogs import (LogWindow, CustomCommandDialog, FFmpegCheckDialog,
|
from ytsage_gui_dialogs import (LogWindow, CustomCommandDialog, FFmpegCheckDialog,
|
||||||
YTDLPUpdateDialog, AboutDialog, SubtitleSelectionDialog,
|
YTDLPUpdateDialog, AboutDialog, SubtitleSelectionDialog,
|
||||||
PlaylistSelectionDialog, CookieLoginDialog,
|
PlaylistSelectionDialog, CookieLoginDialog,
|
||||||
DownloadSettingsDialog) # <-- Use renamed dialog
|
DownloadSettingsDialog, CustomOptionsDialog, TimeRangeDialog) # Added TimeRangeDialog
|
||||||
from ytsage_gui_format_table import FormatTableMixin # Import FormatTableMixin
|
from ytsage_gui_format_table import FormatTableMixin # Import FormatTableMixin
|
||||||
from ytsage_gui_video_info import VideoInfoMixin # Import VideoInfoMixin
|
from ytsage_gui_video_info import VideoInfoMixin # Import VideoInfoMixin
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ class YTSageApp(QMainWindow, FormatTableMixin, VideoInfoMixin): # Inherit from m
|
|||||||
if not check_ffmpeg():
|
if not check_ffmpeg():
|
||||||
self.show_ffmpeg_dialog()
|
self.show_ffmpeg_dialog()
|
||||||
|
|
||||||
self.version = "4.5.2"
|
self.version = "4.5.6"
|
||||||
self.check_for_updates()
|
self.check_for_updates()
|
||||||
self.config_file = Path.home() / '.ytsage_config.json'
|
self.config_file = Path.home() / '.ytsage_config.json'
|
||||||
load_saved_path(self)
|
load_saved_path(self)
|
||||||
@@ -69,6 +69,8 @@ class YTSageApp(QMainWindow, FormatTableMixin, VideoInfoMixin): # Inherit from m
|
|||||||
self.cookie_file_path = None # Initialize cookie file path
|
self.cookie_file_path = None # Initialize cookie file path
|
||||||
self.speed_limit_value = None # Store speed limit value
|
self.speed_limit_value = None # Store speed limit value
|
||||||
self.speed_limit_unit_index = 0 # Store speed limit unit index (0: KB/s, 1: MB/s)
|
self.speed_limit_unit_index = 0 # Store speed limit unit index (0: KB/s, 1: MB/s)
|
||||||
|
self.download_section = None
|
||||||
|
self.force_keyframes = False
|
||||||
|
|
||||||
self.init_ui()
|
self.init_ui()
|
||||||
self.setStyleSheet("""
|
self.setStyleSheet("""
|
||||||
@@ -253,7 +255,7 @@ class YTSageApp(QMainWindow, FormatTableMixin, VideoInfoMixin): # Inherit from m
|
|||||||
save_path(self, path) # Call the utility function
|
save_path(self, path) # Call the utility function
|
||||||
|
|
||||||
def init_ui(self):
|
def init_ui(self):
|
||||||
self.setWindowTitle('YTSage v4.5.2')
|
self.setWindowTitle('YTSage v4.5.6')
|
||||||
self.setMinimumSize(900, 750)
|
self.setMinimumSize(900, 750)
|
||||||
|
|
||||||
# Main widget and layout
|
# Main widget and layout
|
||||||
@@ -492,20 +494,20 @@ class YTSageApp(QMainWindow, FormatTableMixin, VideoInfoMixin): # Inherit from m
|
|||||||
# Download section
|
# Download section
|
||||||
download_layout = QHBoxLayout()
|
download_layout = QHBoxLayout()
|
||||||
|
|
||||||
# Add existing buttons
|
# Replace the two separate buttons with a single Custom Options button
|
||||||
self.custom_cmd_btn = QPushButton('Custom Command')
|
self.custom_options_btn = QPushButton('Custom Options')
|
||||||
self.custom_cmd_btn.clicked.connect(self.show_custom_command)
|
self.custom_options_btn.clicked.connect(self.show_custom_options)
|
||||||
|
|
||||||
# New button for cookie login
|
|
||||||
self.cookie_login_button = QPushButton("Login with Cookies")
|
|
||||||
self.cookie_login_button.clicked.connect(self.show_cookie_login_dialog) # Connect to a new method
|
|
||||||
|
|
||||||
self.update_ytdlp_btn = QPushButton('Update yt-dlp')
|
|
||||||
self.update_ytdlp_btn.clicked.connect(self.update_ytdlp)
|
|
||||||
|
|
||||||
self.about_btn = QPushButton('About')
|
self.about_btn = QPushButton('About')
|
||||||
self.about_btn.clicked.connect(self.show_about_dialog)
|
self.about_btn.clicked.connect(self.show_about_dialog)
|
||||||
|
|
||||||
|
# Add new Time Range button
|
||||||
|
self.time_range_btn = QPushButton('Trim Video')
|
||||||
|
self.time_range_btn.clicked.connect(self.show_time_range_dialog)
|
||||||
|
|
||||||
|
self.update_ytdlp_btn = QPushButton('Update yt-dlp')
|
||||||
|
self.update_ytdlp_btn.clicked.connect(self.update_ytdlp)
|
||||||
|
|
||||||
# --- Rename Path Button to Settings Button ---
|
# --- Rename Path Button to Settings Button ---
|
||||||
self.settings_button = QPushButton("Download Settings") # Renamed button
|
self.settings_button = QPushButton("Download Settings") # Renamed button
|
||||||
self.settings_button.clicked.connect(self.show_download_settings_dialog) # Renamed method
|
self.settings_button.clicked.connect(self.show_download_settings_dialog) # Renamed method
|
||||||
@@ -525,10 +527,10 @@ class YTSageApp(QMainWindow, FormatTableMixin, VideoInfoMixin): # Inherit from m
|
|||||||
self.cancel_btn.setVisible(False) # Hidden initially
|
self.cancel_btn.setVisible(False) # Hidden initially
|
||||||
|
|
||||||
# Add all buttons to layout in the correct order
|
# Add all buttons to layout in the correct order
|
||||||
download_layout.addWidget(self.custom_cmd_btn)
|
download_layout.addWidget(self.custom_options_btn)
|
||||||
download_layout.addWidget(self.cookie_login_button)
|
|
||||||
download_layout.addWidget(self.update_ytdlp_btn)
|
|
||||||
download_layout.addWidget(self.about_btn)
|
download_layout.addWidget(self.about_btn)
|
||||||
|
download_layout.addWidget(self.time_range_btn) # New button position
|
||||||
|
download_layout.addWidget(self.update_ytdlp_btn)
|
||||||
download_layout.addWidget(self.settings_button)
|
download_layout.addWidget(self.settings_button)
|
||||||
download_layout.addWidget(self.download_btn)
|
download_layout.addWidget(self.download_btn)
|
||||||
download_layout.addWidget(self.pause_btn)
|
download_layout.addWidget(self.pause_btn)
|
||||||
@@ -910,7 +912,9 @@ class YTSageApp(QMainWindow, FormatTableMixin, VideoInfoMixin): # Inherit from m
|
|||||||
playlist_items=playlist_items_to_download, # Pass the selection string
|
playlist_items=playlist_items_to_download, # Pass the selection string
|
||||||
save_description=self.save_description, # Pass the new flag here
|
save_description=self.save_description, # Pass the new flag here
|
||||||
cookie_file=self.cookie_file_path, # Pass the cookie file path
|
cookie_file=self.cookie_file_path, # Pass the cookie file path
|
||||||
rate_limit=rate_limit # Pass the calculated rate limit
|
rate_limit=rate_limit, # Pass the calculated rate limit
|
||||||
|
download_section=self.download_section, # Pass the download section
|
||||||
|
force_keyframes=self.force_keyframes # Pass the force keyframes setting
|
||||||
)
|
)
|
||||||
|
|
||||||
# Connect signals
|
# Connect signals
|
||||||
@@ -1099,71 +1103,18 @@ class YTSageApp(QMainWindow, FormatTableMixin, VideoInfoMixin): # Inherit from m
|
|||||||
def open_release_page(self, url):
|
def open_release_page(self, url):
|
||||||
webbrowser.open(url)
|
webbrowser.open(url)
|
||||||
|
|
||||||
def show_custom_command(self):
|
def show_custom_options(self):
|
||||||
dialog = CustomCommandDialog(self)
|
dialog = CustomOptionsDialog(self)
|
||||||
dialog.exec()
|
if dialog.exec():
|
||||||
|
# Handle cookies if set
|
||||||
def cancel_download(self):
|
cookie_path = dialog.get_cookie_file_path()
|
||||||
if self.current_download:
|
if cookie_path:
|
||||||
self.current_download.cancelled = True
|
self.cookie_file_path = cookie_path
|
||||||
self.status_label.setText("Cancelling download...") # Set status directly
|
print(f"Selected cookie file: {self.cookie_file_path}")
|
||||||
self.download_details_label.setText("") # Clear details label on cancellation
|
QMessageBox.information(self, "Cookie File Selected", f"Cookie file selected: {self.cookie_file_path}")
|
||||||
|
else:
|
||||||
def show_ffmpeg_dialog(self):
|
# Don't clear the cookie path if nothing was selected
|
||||||
dialog = FFmpegCheckDialog(self)
|
pass
|
||||||
dialog.exec()
|
|
||||||
|
|
||||||
def toggle_download_controls(self, enabled=True):
|
|
||||||
"""Enable or disable download-related controls"""
|
|
||||||
self.url_input.setEnabled(enabled)
|
|
||||||
self.analyze_button.setEnabled(enabled)
|
|
||||||
self.format_table.setEnabled(enabled) # Changed from format_scroll_area to format_table
|
|
||||||
self.download_btn.setEnabled(enabled)
|
|
||||||
if hasattr(self, 'subtitle_combo'):
|
|
||||||
self.subtitle_combo.setEnabled(enabled)
|
|
||||||
self.video_button.setEnabled(enabled)
|
|
||||||
self.audio_button.setEnabled(enabled)
|
|
||||||
self.sponsorblock_checkbox.setEnabled(enabled)
|
|
||||||
self.merge_subs_checkbox.setEnabled(enabled) # Enable/disable merge subs checkbox
|
|
||||||
self.custom_cmd_btn.setEnabled(enabled) # Enable/disable custom command button
|
|
||||||
self.cookie_login_button.setEnabled(enabled) # Enable/disable login button
|
|
||||||
self.update_ytdlp_btn.setEnabled(enabled) # Enable/disable update button
|
|
||||||
self.settings_button.setEnabled(enabled) # Enable/disable settings button
|
|
||||||
|
|
||||||
# Clear progress/status when controls are re-enabled
|
|
||||||
if enabled:
|
|
||||||
self.progress_bar.setValue(0)
|
|
||||||
self.status_label.setText("Ready")
|
|
||||||
self.download_details_label.setText("") # Clear details label
|
|
||||||
|
|
||||||
def handle_format_selection(self, button):
|
|
||||||
# Update formats
|
|
||||||
self.filter_formats()
|
|
||||||
|
|
||||||
def handle_mode_change(self):
|
|
||||||
"""Enable or disable features based on video/audio mode"""
|
|
||||||
if self.audio_button.isChecked():
|
|
||||||
# In Audio Only mode, disable video-specific features
|
|
||||||
self.sponsorblock_checkbox.setEnabled(False)
|
|
||||||
self.sponsorblock_checkbox.setChecked(False) # Uncheck when disabled
|
|
||||||
self.merge_subs_checkbox.setEnabled(False)
|
|
||||||
self.merge_subs_checkbox.setChecked(False) # Uncheck when disabled
|
|
||||||
|
|
||||||
# Allow subtitle selection in Audio Only mode too
|
|
||||||
if hasattr(self, 'subtitle_select_btn'):
|
|
||||||
self.subtitle_select_btn.setEnabled(True)
|
|
||||||
else:
|
|
||||||
# In Video mode, enable video-specific features
|
|
||||||
self.sponsorblock_checkbox.setEnabled(True)
|
|
||||||
# Don't auto-check - leave it to user preference
|
|
||||||
|
|
||||||
# Enable merge_subs only if subtitles are selected
|
|
||||||
has_subs_selected = len(getattr(self, 'selected_subtitles', [])) > 0
|
|
||||||
self.merge_subs_checkbox.setEnabled(has_subs_selected)
|
|
||||||
|
|
||||||
# Re-enable subtitle selection button in Video mode
|
|
||||||
if hasattr(self, 'subtitle_select_btn'):
|
|
||||||
self.subtitle_select_btn.setEnabled(True)
|
|
||||||
|
|
||||||
def show_about_dialog(self): # ADDED METHOD HERE
|
def show_about_dialog(self): # ADDED METHOD HERE
|
||||||
dialog = AboutDialog(self)
|
dialog = AboutDialog(self)
|
||||||
@@ -1268,12 +1219,112 @@ class YTSageApp(QMainWindow, FormatTableMixin, VideoInfoMixin): # Inherit from m
|
|||||||
self.playlist_select_btn.setText(text)
|
self.playlist_select_btn.setText(text)
|
||||||
# --- End New Slot ---
|
# --- End New Slot ---
|
||||||
|
|
||||||
|
def toggle_download_controls(self, enabled=True):
|
||||||
|
"""Enable or disable download-related controls"""
|
||||||
|
self.url_input.setEnabled(enabled)
|
||||||
|
self.analyze_button.setEnabled(enabled)
|
||||||
|
self.format_table.setEnabled(enabled) # Changed from format_scroll_area to format_table
|
||||||
|
self.download_btn.setEnabled(enabled)
|
||||||
|
if hasattr(self, 'subtitle_combo'):
|
||||||
|
self.subtitle_combo.setEnabled(enabled)
|
||||||
|
self.video_button.setEnabled(enabled)
|
||||||
|
self.audio_button.setEnabled(enabled)
|
||||||
|
self.sponsorblock_checkbox.setEnabled(enabled)
|
||||||
|
self.merge_subs_checkbox.setEnabled(enabled) # Enable/disable merge subs checkbox
|
||||||
|
self.custom_options_btn.setEnabled(enabled) # Enable/disable custom options button
|
||||||
|
self.update_ytdlp_btn.setEnabled(enabled) # Enable/disable update button
|
||||||
|
self.time_range_btn.setEnabled(enabled) # Enable/disable time range button
|
||||||
|
self.settings_button.setEnabled(enabled) # Enable/disable settings button
|
||||||
|
|
||||||
|
# Clear progress/status when controls are re-enabled
|
||||||
|
if enabled:
|
||||||
|
self.progress_bar.setValue(0)
|
||||||
|
self.status_label.setText("Ready")
|
||||||
|
self.download_details_label.setText("") # Clear details label
|
||||||
|
|
||||||
|
def handle_format_selection(self, button):
|
||||||
|
# Update formats
|
||||||
|
self.filter_formats()
|
||||||
|
|
||||||
|
def handle_mode_change(self):
|
||||||
|
"""Enable or disable features based on video/audio mode"""
|
||||||
|
if self.audio_button.isChecked():
|
||||||
|
# In Audio Only mode, disable video-specific features
|
||||||
|
self.sponsorblock_checkbox.setEnabled(False)
|
||||||
|
self.sponsorblock_checkbox.setChecked(False) # Uncheck when disabled
|
||||||
|
self.merge_subs_checkbox.setEnabled(False)
|
||||||
|
self.merge_subs_checkbox.setChecked(False) # Uncheck when disabled
|
||||||
|
|
||||||
|
# Allow subtitle selection in Audio Only mode too
|
||||||
|
if hasattr(self, 'subtitle_select_btn'):
|
||||||
|
self.subtitle_select_btn.setEnabled(True)
|
||||||
|
else:
|
||||||
|
# In Video mode, enable video-specific features
|
||||||
|
self.sponsorblock_checkbox.setEnabled(True)
|
||||||
|
# Don't auto-check - leave it to user preference
|
||||||
|
|
||||||
|
# Enable merge_subs only if subtitles are selected
|
||||||
|
has_subs_selected = len(getattr(self, 'selected_subtitles', [])) > 0
|
||||||
|
self.merge_subs_checkbox.setEnabled(has_subs_selected)
|
||||||
|
|
||||||
|
# Re-enable subtitle selection button in Video mode
|
||||||
|
if hasattr(self, 'subtitle_select_btn'):
|
||||||
|
self.subtitle_select_btn.setEnabled(True)
|
||||||
|
|
||||||
|
# Keep these methods for backwards compatibility - they just call the new dialog now
|
||||||
|
def show_custom_command(self):
|
||||||
|
dialog = CustomOptionsDialog(self)
|
||||||
|
dialog.tab_widget.setCurrentIndex(1) # Select the Custom Command tab
|
||||||
|
dialog.exec()
|
||||||
|
|
||||||
def show_cookie_login_dialog(self):
|
def show_cookie_login_dialog(self):
|
||||||
dialog = CookieLoginDialog(self)
|
dialog = CustomOptionsDialog(self)
|
||||||
|
dialog.tab_widget.setCurrentIndex(0) # Select the Cookie Login tab
|
||||||
if dialog.exec():
|
if dialog.exec():
|
||||||
self.cookie_file_path = dialog.get_cookie_file_path()
|
self.cookie_file_path = dialog.get_cookie_file_path()
|
||||||
if self.cookie_file_path:
|
if self.cookie_file_path:
|
||||||
print(f"Selected cookie file: {self.cookie_file_path}") # For debugging
|
print(f"Selected cookie file: {self.cookie_file_path}")
|
||||||
QMessageBox.information(self, "Cookie File Selected", f"Cookie file selected: {self.cookie_file_path}")
|
QMessageBox.information(self, "Cookie File Selected", f"Cookie file selected: {self.cookie_file_path}")
|
||||||
else:
|
else:
|
||||||
self.cookie_file_path = None # Clear path if dialog accepted but no file selected
|
self.cookie_file_path = None # Clear path if dialog accepted but no file selected
|
||||||
|
|
||||||
|
def cancel_download(self):
|
||||||
|
if self.current_download:
|
||||||
|
self.current_download.cancelled = True
|
||||||
|
self.status_label.setText("Cancelling download...") # Set status directly
|
||||||
|
self.download_details_label.setText("") # Clear details label on cancellation
|
||||||
|
|
||||||
|
def show_ffmpeg_dialog(self):
|
||||||
|
dialog = FFmpegCheckDialog(self)
|
||||||
|
dialog.exec()
|
||||||
|
|
||||||
|
# Add method for showing time range dialog
|
||||||
|
def show_time_range_dialog(self):
|
||||||
|
dialog = TimeRangeDialog(self)
|
||||||
|
if dialog.exec():
|
||||||
|
# Store the time range settings
|
||||||
|
self.download_section = dialog.get_download_sections()
|
||||||
|
self.force_keyframes = dialog.get_force_keyframes()
|
||||||
|
|
||||||
|
if self.download_section:
|
||||||
|
self.time_range_btn.setStyleSheet("""
|
||||||
|
QPushButton {
|
||||||
|
padding: 8px 15px;
|
||||||
|
background-color: #c90000;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
border: 2px solid white;
|
||||||
|
}
|
||||||
|
QPushButton:hover {
|
||||||
|
background-color: #a50000;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
self.time_range_btn.setToolTip(f"Section set: {self.download_section}")
|
||||||
|
else:
|
||||||
|
# Reset to default style if no section is selected
|
||||||
|
self.download_section = None
|
||||||
|
self.force_keyframes = False
|
||||||
|
self.time_range_btn.setStyleSheet("")
|
||||||
|
self.time_range_btn.setToolTip("")
|
||||||
Reference in New Issue
Block a user