Merge cookie/custom dialogs; add trim dialog
This commit is contained in:
+499
-2
@@ -5,7 +5,7 @@ from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
|
|||||||
QHBoxLayout, QLineEdit, QPushButton, QTableWidget,
|
QHBoxLayout, QLineEdit, QPushButton, QTableWidget,
|
||||||
QTableWidgetItem, QProgressBar, QLabel, QFileDialog,
|
QTableWidgetItem, QProgressBar, QLabel, QFileDialog,
|
||||||
QHeaderView, QStyle, QStyleFactory, QComboBox, QTextEdit, QDialog, QPlainTextEdit, QCheckBox, QButtonGroup, QListWidget,
|
QHeaderView, QStyle, QStyleFactory, QComboBox, QTextEdit, QDialog, QPlainTextEdit, QCheckBox, QButtonGroup, QListWidget,
|
||||||
QListWidgetItem, QDialogButtonBox, QScrollArea, QGroupBox)
|
QListWidgetItem, QDialogButtonBox, QScrollArea, QGroupBox, QTabWidget)
|
||||||
from PySide6.QtCore import Qt, Signal, QObject, QThread, QProcess
|
from PySide6.QtCore import Qt, Signal, QObject, QThread, QProcess
|
||||||
from PySide6.QtGui import QIcon, QPalette, QColor, QPixmap
|
from PySide6.QtGui import QIcon, QPalette, QColor, QPixmap
|
||||||
import requests
|
import requests
|
||||||
@@ -1296,4 +1296,501 @@ class DownloadSettingsDialog(QDialog): # Renamed class
|
|||||||
|
|
||||||
def get_selected_unit_index(self):
|
def get_selected_unit_index(self):
|
||||||
"""Returns the index of the selected speed limit unit."""
|
"""Returns the index of the selected speed limit unit."""
|
||||||
return self.speed_limit_unit.currentIndex()
|
return self.speed_limit_unit.currentIndex()
|
||||||
|
|
||||||
|
# === New CustomOptions Dialog combining Cookies and Custom Commands ===
|
||||||
|
class CustomOptionsDialog(QDialog):
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.parent = parent
|
||||||
|
self.setWindowTitle('Custom Options')
|
||||||
|
self.setMinimumSize(600, 500)
|
||||||
|
|
||||||
|
layout = QVBoxLayout(self)
|
||||||
|
|
||||||
|
# Create tab widget to organize content
|
||||||
|
self.tab_widget = QTabWidget()
|
||||||
|
layout.addWidget(self.tab_widget)
|
||||||
|
|
||||||
|
# === Cookies Tab ===
|
||||||
|
cookies_tab = QWidget()
|
||||||
|
cookies_layout = QVBoxLayout(cookies_tab)
|
||||||
|
|
||||||
|
# Help text
|
||||||
|
help_text = QLabel(
|
||||||
|
"Select the Netscape-format cookies file for logging in.\n"
|
||||||
|
"This allows downloading of private videos and premium quality audio."
|
||||||
|
)
|
||||||
|
help_text.setWordWrap(True)
|
||||||
|
help_text.setStyleSheet("color: #999999; padding: 10px;")
|
||||||
|
cookies_layout.addWidget(help_text)
|
||||||
|
|
||||||
|
# File path input and browse button
|
||||||
|
path_layout = QHBoxLayout()
|
||||||
|
self.cookie_path_input = QLineEdit()
|
||||||
|
self.cookie_path_input.setPlaceholderText("Path to cookies file (Netscape format)")
|
||||||
|
if hasattr(parent, 'cookie_file_path') and parent.cookie_file_path:
|
||||||
|
self.cookie_path_input.setText(parent.cookie_file_path)
|
||||||
|
path_layout.addWidget(self.cookie_path_input)
|
||||||
|
|
||||||
|
self.browse_button = QPushButton("Browse")
|
||||||
|
self.browse_button.clicked.connect(self.browse_cookie_file)
|
||||||
|
path_layout.addWidget(self.browse_button)
|
||||||
|
cookies_layout.addLayout(path_layout) # Add the horizontal layout to cookies layout
|
||||||
|
|
||||||
|
# Status indicator for cookies
|
||||||
|
self.cookie_status = QLabel("")
|
||||||
|
self.cookie_status.setStyleSheet("color: #999999; font-style: italic;")
|
||||||
|
cookies_layout.addWidget(self.cookie_status)
|
||||||
|
|
||||||
|
cookies_layout.addStretch()
|
||||||
|
|
||||||
|
# === Custom Command Tab ===
|
||||||
|
command_tab = QWidget()
|
||||||
|
command_layout = QVBoxLayout(command_tab)
|
||||||
|
|
||||||
|
# Help text
|
||||||
|
cmd_help_text = QLabel(
|
||||||
|
"Enter custom yt-dlp commands below. The URL will be automatically appended.\n"
|
||||||
|
"Example: --extract-audio --audio-format mp3 --audio-quality 0\n"
|
||||||
|
"Note: Download path and output template will be preserved."
|
||||||
|
)
|
||||||
|
cmd_help_text.setWordWrap(True)
|
||||||
|
cmd_help_text.setStyleSheet("color: #999999; padding: 10px;")
|
||||||
|
command_layout.addWidget(cmd_help_text)
|
||||||
|
|
||||||
|
# Add SponsorBlock checkbox
|
||||||
|
self.sponsorblock_checkbox = QCheckBox("Remove Sponsor Segments")
|
||||||
|
self.sponsorblock_checkbox.setStyleSheet("""
|
||||||
|
QCheckBox {
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 5px;
|
||||||
|
margin-left: 0px;
|
||||||
|
}
|
||||||
|
QCheckBox::indicator {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
border-radius: 9px;
|
||||||
|
}
|
||||||
|
QCheckBox::indicator:unchecked {
|
||||||
|
border: 2px solid #666666;
|
||||||
|
background: #1d1e22;
|
||||||
|
border-radius: 9px;
|
||||||
|
}
|
||||||
|
QCheckBox::indicator:checked {
|
||||||
|
border: 2px solid #c90000;
|
||||||
|
background: #c90000;
|
||||||
|
border-radius: 9px;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
command_layout.addWidget(self.sponsorblock_checkbox)
|
||||||
|
|
||||||
|
# Command input
|
||||||
|
self.command_input = QPlainTextEdit()
|
||||||
|
self.command_input.setPlaceholderText("Enter yt-dlp arguments...")
|
||||||
|
self.command_input.setStyleSheet("""
|
||||||
|
QPlainTextEdit {
|
||||||
|
background-color: #1d1e22;
|
||||||
|
color: #ffffff;
|
||||||
|
border: 2px solid #1d1e22;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 8px;
|
||||||
|
font-family: Consolas, monospace;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
command_layout.addWidget(self.command_input)
|
||||||
|
|
||||||
|
# Run command button
|
||||||
|
self.run_btn = QPushButton("Run Command")
|
||||||
|
self.run_btn.clicked.connect(self.run_custom_command)
|
||||||
|
command_layout.addWidget(self.run_btn)
|
||||||
|
|
||||||
|
# Log output
|
||||||
|
self.log_output = QTextEdit()
|
||||||
|
self.log_output.setReadOnly(True)
|
||||||
|
self.log_output.setStyleSheet("""
|
||||||
|
QTextEdit {
|
||||||
|
background-color: #1d1e22;
|
||||||
|
color: #ffffff;
|
||||||
|
border: 2px solid #1d1e22;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 8px;
|
||||||
|
font-family: Consolas, monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
command_layout.addWidget(self.log_output)
|
||||||
|
|
||||||
|
# Add tabs to the tab widget
|
||||||
|
self.tab_widget.addTab(cookies_tab, "Login with Cookies")
|
||||||
|
self.tab_widget.addTab(command_tab, "Custom Command")
|
||||||
|
|
||||||
|
# Dialog buttons
|
||||||
|
button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||||
|
button_box.accepted.connect(self.accept)
|
||||||
|
button_box.rejected.connect(self.reject)
|
||||||
|
layout.addWidget(button_box)
|
||||||
|
|
||||||
|
# Apply global styles
|
||||||
|
self.setStyleSheet("""
|
||||||
|
QDialog {
|
||||||
|
background-color: #15181b;
|
||||||
|
}
|
||||||
|
QTabWidget::pane {
|
||||||
|
border: 1px solid #3d3d3d;
|
||||||
|
background-color: #15181b;
|
||||||
|
}
|
||||||
|
QTabBar::tab {
|
||||||
|
background-color: #1d1e22;
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border: 1px solid #3d3d3d;
|
||||||
|
border-bottom: none;
|
||||||
|
border-top-left-radius: 4px;
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
}
|
||||||
|
QTabBar::tab:selected {
|
||||||
|
background-color: #c90000;
|
||||||
|
}
|
||||||
|
QTabBar::tab:hover:!selected {
|
||||||
|
background-color: #2a2d36;
|
||||||
|
}
|
||||||
|
QLabel {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
QLineEdit {
|
||||||
|
padding: 8px;
|
||||||
|
border: 2px solid #1b2021;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #1b2021;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
QPushButton {
|
||||||
|
padding: 8px 15px;
|
||||||
|
background-color: #c90000;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
QPushButton:hover {
|
||||||
|
background-color: #a50000;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
|
||||||
|
def browse_cookie_file(self):
|
||||||
|
# Open file dialog to select cookie file
|
||||||
|
file_dialog = QFileDialog(self)
|
||||||
|
file_dialog.setFileMode(QFileDialog.ExistingFile)
|
||||||
|
file_dialog.setNameFilter("Cookies files (*.txt *.lwp)") # Assuming common cookie file extensions
|
||||||
|
if file_dialog.exec():
|
||||||
|
selected_files = file_dialog.selectedFiles()
|
||||||
|
if selected_files:
|
||||||
|
self.cookie_path_input.setText(selected_files[0])
|
||||||
|
self.cookie_status.setText("Cookie file selected - Click OK to apply")
|
||||||
|
self.cookie_status.setStyleSheet("color: #00cc00; font-style: italic;")
|
||||||
|
|
||||||
|
def get_cookie_file_path(self):
|
||||||
|
# Return the selected cookie file path if it's not empty
|
||||||
|
path = self.cookie_path_input.text().strip()
|
||||||
|
if path and os.path.exists(path):
|
||||||
|
return path
|
||||||
|
return None
|
||||||
|
|
||||||
|
def run_custom_command(self):
|
||||||
|
url = self.parent.url_input.text().strip()
|
||||||
|
if not url:
|
||||||
|
self.log_output.append("Error: No URL provided")
|
||||||
|
return
|
||||||
|
|
||||||
|
command = self.command_input.toPlainText().strip()
|
||||||
|
|
||||||
|
# Get download path from parent
|
||||||
|
path = self.parent.last_path
|
||||||
|
|
||||||
|
self.log_output.clear()
|
||||||
|
self.log_output.append(f"Running command with URL: {url}")
|
||||||
|
self.run_btn.setEnabled(False)
|
||||||
|
|
||||||
|
# Start command in thread
|
||||||
|
import threading
|
||||||
|
threading.Thread(target=self._run_command_thread,
|
||||||
|
args=(command, url, path),
|
||||||
|
daemon=True).start()
|
||||||
|
|
||||||
|
def _run_command_thread(self, command, url, path):
|
||||||
|
try:
|
||||||
|
class CommandLogger:
|
||||||
|
def debug(self, msg):
|
||||||
|
from PySide6.QtCore import QMetaObject, Qt, Q_ARG
|
||||||
|
QMetaObject.invokeMethod(
|
||||||
|
self.dialog.log_output, "append", Qt.ConnectionType.QueuedConnection,
|
||||||
|
Q_ARG(str, msg)
|
||||||
|
)
|
||||||
|
def warning(self, msg):
|
||||||
|
from PySide6.QtCore import QMetaObject, Qt, Q_ARG
|
||||||
|
QMetaObject.invokeMethod(
|
||||||
|
self.dialog.log_output, "append", Qt.ConnectionType.QueuedConnection,
|
||||||
|
Q_ARG(str, f"Warning: {msg}")
|
||||||
|
)
|
||||||
|
def error(self, msg):
|
||||||
|
from PySide6.QtCore import QMetaObject, Qt, Q_ARG
|
||||||
|
QMetaObject.invokeMethod(
|
||||||
|
self.dialog.log_output, "append", Qt.ConnectionType.QueuedConnection,
|
||||||
|
Q_ARG(str, f"Error: {msg}")
|
||||||
|
)
|
||||||
|
def __init__(self, dialog):
|
||||||
|
self.dialog = dialog
|
||||||
|
|
||||||
|
# Split command into arguments
|
||||||
|
args = command.split()
|
||||||
|
|
||||||
|
# Base options
|
||||||
|
ydl_opts = {
|
||||||
|
'logger': CommandLogger(self),
|
||||||
|
'paths': {'home': path},
|
||||||
|
'debug_printout': True,
|
||||||
|
'postprocessors': []
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add SponsorBlock if selected
|
||||||
|
if self.sponsorblock_checkbox.isChecked():
|
||||||
|
ydl_opts['postprocessors'].append({
|
||||||
|
'key': 'SponsorBlock',
|
||||||
|
'categories': ['sponsor', 'intro', 'outro', 'selfpromo', 'preview', 'filler']
|
||||||
|
})
|
||||||
|
|
||||||
|
# Parse additional options
|
||||||
|
yt_dlp_path = get_yt_dlp_path()
|
||||||
|
base_cmd = [yt_dlp_path] + args + [url]
|
||||||
|
|
||||||
|
# Show the full command
|
||||||
|
from PySide6.QtCore import QMetaObject, Qt, Q_ARG
|
||||||
|
QMetaObject.invokeMethod(
|
||||||
|
self.log_output, "append", Qt.ConnectionType.QueuedConnection,
|
||||||
|
Q_ARG(str, f"Full command: {' '.join(base_cmd)}")
|
||||||
|
)
|
||||||
|
|
||||||
|
# Run the command
|
||||||
|
proc = subprocess.Popen(
|
||||||
|
base_cmd,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT,
|
||||||
|
text=True,
|
||||||
|
encoding='utf-8',
|
||||||
|
errors='replace'
|
||||||
|
)
|
||||||
|
|
||||||
|
# Stream output
|
||||||
|
for line in proc.stdout:
|
||||||
|
QMetaObject.invokeMethod(
|
||||||
|
self.log_output, "append", Qt.ConnectionType.QueuedConnection,
|
||||||
|
Q_ARG(str, line.rstrip())
|
||||||
|
)
|
||||||
|
|
||||||
|
ret = proc.wait()
|
||||||
|
if ret != 0:
|
||||||
|
QMetaObject.invokeMethod(
|
||||||
|
self.log_output, "append", Qt.ConnectionType.QueuedConnection,
|
||||||
|
Q_ARG(str, f"Command exited with code {ret}")
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
QMetaObject.invokeMethod(
|
||||||
|
self.log_output, "append", Qt.ConnectionType.QueuedConnection,
|
||||||
|
Q_ARG(str, "Command completed successfully")
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
from PySide6.QtCore import QMetaObject, Qt, Q_ARG
|
||||||
|
QMetaObject.invokeMethod(
|
||||||
|
self.log_output, "append", Qt.ConnectionType.QueuedConnection,
|
||||||
|
Q_ARG(str, f"Error: {str(e)}")
|
||||||
|
)
|
||||||
|
finally:
|
||||||
|
# Re-enable the run button
|
||||||
|
QMetaObject.invokeMethod(
|
||||||
|
self.run_btn, "setEnabled", Qt.ConnectionType.QueuedConnection,
|
||||||
|
Q_ARG(bool, True)
|
||||||
|
)
|
||||||
|
# === End of CustomOptionsDialog ===
|
||||||
|
|
||||||
|
# === Time Range Selection Dialog ===
|
||||||
|
class TimeRangeDialog(QDialog):
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.parent = parent
|
||||||
|
self.setWindowTitle('Download Video Section')
|
||||||
|
self.setMinimumWidth(400)
|
||||||
|
|
||||||
|
layout = QVBoxLayout(self)
|
||||||
|
|
||||||
|
# Help text explaining the feature
|
||||||
|
help_text = QLabel(
|
||||||
|
"Download only specific parts of a video by specifying time ranges.\n"
|
||||||
|
"Use HH:MM:SS format or seconds. Leave start or end empty to download from beginning or to end."
|
||||||
|
)
|
||||||
|
help_text.setWordWrap(True)
|
||||||
|
help_text.setStyleSheet("color: #999999; padding: 10px;")
|
||||||
|
layout.addWidget(help_text)
|
||||||
|
|
||||||
|
# Time range section
|
||||||
|
time_group = QGroupBox("Time Range")
|
||||||
|
time_layout = QVBoxLayout()
|
||||||
|
|
||||||
|
# Start time row
|
||||||
|
start_layout = QHBoxLayout()
|
||||||
|
start_layout.addWidget(QLabel("Start Time:"))
|
||||||
|
self.start_time_input = QLineEdit()
|
||||||
|
self.start_time_input.setPlaceholderText("00:00:00 (or leave empty for start)")
|
||||||
|
start_layout.addWidget(self.start_time_input)
|
||||||
|
time_layout.addLayout(start_layout)
|
||||||
|
|
||||||
|
# End time row
|
||||||
|
end_layout = QHBoxLayout()
|
||||||
|
end_layout.addWidget(QLabel("End Time:"))
|
||||||
|
self.end_time_input = QLineEdit()
|
||||||
|
self.end_time_input.setPlaceholderText("00:10:00 (or leave empty for end)")
|
||||||
|
end_layout.addWidget(self.end_time_input)
|
||||||
|
time_layout.addLayout(end_layout)
|
||||||
|
|
||||||
|
time_group.setLayout(time_layout)
|
||||||
|
layout.addWidget(time_group)
|
||||||
|
|
||||||
|
# Force keyframes option
|
||||||
|
self.force_keyframes = QCheckBox("Force keyframes at cuts (better accuracy, slower)")
|
||||||
|
self.force_keyframes.setChecked(True)
|
||||||
|
self.force_keyframes.setStyleSheet("""
|
||||||
|
QCheckBox {
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
QCheckBox::indicator {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
QCheckBox::indicator:unchecked {
|
||||||
|
border: 2px solid #666666;
|
||||||
|
background: #1d1e22;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
QCheckBox::indicator:checked {
|
||||||
|
border: 2px solid #c90000;
|
||||||
|
background: #c90000;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
layout.addWidget(self.force_keyframes)
|
||||||
|
|
||||||
|
# Format preview
|
||||||
|
preview_group = QGroupBox("Command Preview")
|
||||||
|
preview_layout = QVBoxLayout()
|
||||||
|
self.preview_label = QLabel("--download-sections \"*-\"")
|
||||||
|
self.preview_label.setStyleSheet("""
|
||||||
|
QLabel {
|
||||||
|
background-color: #1d1e22;
|
||||||
|
color: #ffffff;
|
||||||
|
border: 1px solid #3d3d3d;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 8px;
|
||||||
|
font-family: Consolas, monospace;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
preview_layout.addWidget(self.preview_label)
|
||||||
|
preview_group.setLayout(preview_layout)
|
||||||
|
layout.addWidget(preview_group)
|
||||||
|
|
||||||
|
# Connect signals for live preview updates
|
||||||
|
self.start_time_input.textChanged.connect(self.update_preview)
|
||||||
|
self.end_time_input.textChanged.connect(self.update_preview)
|
||||||
|
self.force_keyframes.stateChanged.connect(self.update_preview)
|
||||||
|
|
||||||
|
# Buttons
|
||||||
|
button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||||
|
button_box.accepted.connect(self.accept)
|
||||||
|
button_box.rejected.connect(self.reject)
|
||||||
|
layout.addWidget(button_box)
|
||||||
|
|
||||||
|
# Apply styling
|
||||||
|
self.setStyleSheet("""
|
||||||
|
QDialog {
|
||||||
|
background-color: #15181b;
|
||||||
|
}
|
||||||
|
QGroupBox {
|
||||||
|
border: 1px solid #3d3d3d;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-top: 1.5ex;
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
QGroupBox::title {
|
||||||
|
subcontrol-origin: margin;
|
||||||
|
subcontrol-position: top left;
|
||||||
|
padding: 0 5px;
|
||||||
|
}
|
||||||
|
QLabel {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
QLineEdit {
|
||||||
|
padding: 8px;
|
||||||
|
border: 2px solid #1b2021;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #1b2021;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
QPushButton {
|
||||||
|
padding: 8px 15px;
|
||||||
|
background-color: #c90000;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
QPushButton:hover {
|
||||||
|
background-color: #a50000;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
|
||||||
|
# Initialize preview
|
||||||
|
self.update_preview()
|
||||||
|
|
||||||
|
def update_preview(self):
|
||||||
|
start = self.start_time_input.text().strip()
|
||||||
|
end = self.end_time_input.text().strip()
|
||||||
|
|
||||||
|
if start and end:
|
||||||
|
time_range = f"*{start}-{end}"
|
||||||
|
elif start:
|
||||||
|
time_range = f"*{start}-"
|
||||||
|
elif end:
|
||||||
|
time_range = f"*-{end}"
|
||||||
|
else:
|
||||||
|
time_range = "*-" # Full video
|
||||||
|
|
||||||
|
preview = f"--download-sections \"{time_range}\""
|
||||||
|
if self.force_keyframes.isChecked():
|
||||||
|
preview += " --force-keyframes-at-cuts"
|
||||||
|
|
||||||
|
self.preview_label.setText(preview)
|
||||||
|
|
||||||
|
def get_download_sections(self):
|
||||||
|
"""Returns the download sections command arguments or None if no selection made"""
|
||||||
|
start = self.start_time_input.text().strip()
|
||||||
|
end = self.end_time_input.text().strip()
|
||||||
|
|
||||||
|
if not start and not end:
|
||||||
|
return None # No selection made
|
||||||
|
|
||||||
|
if start and end:
|
||||||
|
time_range = f"*{start}-{end}"
|
||||||
|
elif start:
|
||||||
|
time_range = f"*{start}-"
|
||||||
|
elif end:
|
||||||
|
time_range = f"*-{end}"
|
||||||
|
else:
|
||||||
|
return None # Shouldn't happen but just in case
|
||||||
|
|
||||||
|
return time_range
|
||||||
|
|
||||||
|
def get_force_keyframes(self):
|
||||||
|
"""Returns whether to force keyframes at cuts"""
|
||||||
|
return self.force_keyframes.isChecked()
|
||||||
Reference in New Issue
Block a user