feat: side-by-side pinned tabs + optional tab-name in export folder
Side-by-side: - Right-click a tab → "Show side-by-side" to pin it; 2+ pinned tabs render in a horizontal splitter (each with a name header + ✕ to unpin), via a QStackedWidget that swaps between the tab view and split view. - Tabs are now backed by self._pws (source of truth) so persistence and layout work regardless of where each list is parented; pinned state saved. - self._playlist resolves to the last-interacted pane (active pw), so exports and edits follow the pane you're acting in. Pinned flag persisted per profile. Tab → export folder (optional): - New "Tab→folder" checkbox: when on, the active tab's name is appended to the export folder (mp4 → mp4_BatchA). Default "List N" tabs are ignored. - _export_folder()/_export_base_name() helpers route exports, markers, next label, and delete/clear paths so they stay consistent with the tab folder. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3134,8 +3134,12 @@ class SnapPreviewWindow(QWidget):
|
||||
|
||||
|
||||
class _PlaylistTabBar(QTabBar):
|
||||
"""Tab bar whose labels can be renamed by double-clicking."""
|
||||
"""Tab bar whose labels can be renamed by double-clicking.
|
||||
|
||||
Right-click a tab to pin/unpin it for the side-by-side view.
|
||||
"""
|
||||
tab_renamed = pyqtSignal(int, str)
|
||||
pin_toggle_requested = pyqtSignal(int)
|
||||
|
||||
def mouseDoubleClickEvent(self, event):
|
||||
idx = self.tabAt(event.pos())
|
||||
@@ -3144,6 +3148,26 @@ class _PlaylistTabBar(QTabBar):
|
||||
else:
|
||||
super().mouseDoubleClickEvent(event)
|
||||
|
||||
def contextMenuEvent(self, event):
|
||||
idx = self.tabAt(event.pos())
|
||||
if idx < 0:
|
||||
return
|
||||
from PyQt6.QtWidgets import QMenu
|
||||
menu = QMenu(self)
|
||||
act_pin = menu.addAction("Show side-by-side")
|
||||
act_pin.setCheckable(True)
|
||||
pw = None
|
||||
tw = self.parent()
|
||||
if hasattr(tw, "widget"):
|
||||
pw = tw.widget(idx)
|
||||
act_pin.setChecked(bool(getattr(pw, "_pinned", False)))
|
||||
act_rename = menu.addAction("Rename…")
|
||||
chosen = menu.exec(event.globalPos())
|
||||
if chosen == act_pin:
|
||||
self.pin_toggle_requested.emit(idx)
|
||||
elif chosen == act_rename:
|
||||
self._start_edit(idx)
|
||||
|
||||
def _start_edit(self, idx: int) -> None:
|
||||
editor = QLineEdit(self)
|
||||
editor.setText(self.tabText(idx))
|
||||
@@ -3190,6 +3214,8 @@ class PlaylistWidget(QListWidget):
|
||||
self._all_subcat_counts: dict[str, int] = {} # profile-wide folder → count
|
||||
self._separators_before: set[str] = set() # paths that show a separator row above
|
||||
self._missing: set[str] = set() # paths not present on disk
|
||||
self._pinned: bool = False # shown in the side-by-side view
|
||||
self._label: str = "" # tab name (source of truth across views)
|
||||
self._visible: list[str | None] = [] # rows shown; None = separator row
|
||||
self._selected_path: str | None = None
|
||||
self.itemClicked.connect(self._on_item_clicked)
|
||||
@@ -3691,12 +3717,15 @@ class MainWindow(QMainWindow):
|
||||
# Suppress tab persistence until _load_playlist_tabs runs at the end of
|
||||
# __init__ (the profile combo it needs doesn't exist yet).
|
||||
self._loading_tabs = True
|
||||
self._pws: list[PlaylistWidget] = [] # source of truth for all lists
|
||||
self._active_pw: "PlaylistWidget | None" = None # last-interacted list
|
||||
self._playlist_tabs = QTabWidget()
|
||||
self._playlist_tabs.setTabBar(_PlaylistTabBar())
|
||||
self._playlist_tabs.setTabsClosable(True)
|
||||
self._playlist_tabs.setMovable(True)
|
||||
self._playlist_tabs.setDocumentMode(True)
|
||||
self._playlist_tabs.tabBar().tab_renamed.connect(self._on_tab_renamed)
|
||||
self._playlist_tabs.tabBar().pin_toggle_requested.connect(self._on_pin_toggle)
|
||||
self._playlist_tabs.tabCloseRequested.connect(self._on_close_tab)
|
||||
self._playlist_tabs.currentChanged.connect(self._on_tab_changed)
|
||||
self._btn_add_tab = QPushButton("+")
|
||||
@@ -3705,6 +3734,15 @@ class MainWindow(QMainWindow):
|
||||
self._btn_add_tab.clicked.connect(lambda: self._add_playlist_tab())
|
||||
self._playlist_tabs.setCornerWidget(
|
||||
self._btn_add_tab, Qt.Corner.TopRightCorner)
|
||||
# Side-by-side container (shown when 2+ tabs are pinned).
|
||||
self._split_container = QWidget()
|
||||
self._split_layout = QHBoxLayout(self._split_container)
|
||||
self._split_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self._split_layout.setSpacing(2)
|
||||
from PyQt6.QtWidgets import QStackedWidget
|
||||
self._list_stack = QStackedWidget()
|
||||
self._list_stack.addWidget(self._playlist_tabs) # page 0: tabs
|
||||
self._list_stack.addWidget(self._split_container) # page 1: side-by-side
|
||||
# Start with one empty tab; real contents loaded later via _load_playlist_tabs.
|
||||
self._add_playlist_tab("List 1", select=True)
|
||||
|
||||
@@ -3795,6 +3833,16 @@ class MainWindow(QMainWindow):
|
||||
self._btn_folder.setFixedWidth(30)
|
||||
self._btn_folder.setToolTip("Browse for output folder")
|
||||
self._btn_folder.clicked.connect(self._pick_folder)
|
||||
self._chk_tab_folder = QCheckBox("Tab→folder")
|
||||
self._chk_tab_folder.setToolTip(
|
||||
"When on, append the active tab's name to the export folder\n"
|
||||
"(e.g. mp4 → mp4_BatchA) for files in that tab. Default 'List N'\n"
|
||||
"tabs are ignored.")
|
||||
self._chk_tab_folder.setChecked(
|
||||
self._settings.value("tab_in_folder", "false") == "true")
|
||||
self._chk_tab_folder.toggled.connect(
|
||||
lambda v: self._settings.setValue("tab_in_folder", "true" if v else "false"))
|
||||
self._chk_tab_folder.toggled.connect(self._on_tab_folder_toggled)
|
||||
self._spn_resize = QSpinBox()
|
||||
self._spn_resize.setRange(0, 4320)
|
||||
self._spn_resize.setSingleStep(64)
|
||||
@@ -4124,6 +4172,7 @@ class MainWindow(QMainWindow):
|
||||
path_row.addWidget(QLabel("Folder:"))
|
||||
path_row.addWidget(self._txt_folder, stretch=1)
|
||||
path_row.addWidget(self._btn_folder)
|
||||
path_row.addWidget(self._chk_tab_folder)
|
||||
|
||||
# Row 3 — video + encoding settings
|
||||
settings_row = QHBoxLayout()
|
||||
@@ -4203,7 +4252,7 @@ class MainWindow(QMainWindow):
|
||||
left_top.addWidget(self._btn_show_hidden)
|
||||
left_layout.addLayout(left_top)
|
||||
left_layout.addWidget(self._playlist_filter)
|
||||
left_layout.addWidget(self._playlist_tabs)
|
||||
left_layout.addWidget(self._list_stack)
|
||||
|
||||
# Scan results panel (right side)
|
||||
self._scan_panel = ScanResultsPanel(self._db)
|
||||
@@ -4408,15 +4457,44 @@ class MainWindow(QMainWindow):
|
||||
|
||||
@property
|
||||
def _playlist(self) -> "PlaylistWidget":
|
||||
"""The PlaylistWidget of the currently active file-list tab."""
|
||||
return self._playlist_tabs.currentWidget()
|
||||
"""The active file list — the last-interacted pane/tab."""
|
||||
if self._active_pw is not None and self._active_pw in self._pws:
|
||||
return self._active_pw
|
||||
w = self._playlist_tabs.currentWidget()
|
||||
if w is not None:
|
||||
return w
|
||||
return self._pws[0] if self._pws else None
|
||||
|
||||
# ── Export folder (optionally tagged with the active tab name) ──
|
||||
def _active_tab_name(self) -> str:
|
||||
"""Sanitized name of the active tab, or "" for default 'List N' tabs."""
|
||||
pw = self._playlist
|
||||
label = "" if pw is None else (getattr(pw, "_label", "") or "")
|
||||
label = label.strip().replace(" ", "_")
|
||||
if not label or (label.startswith("List_") and label[5:].isdigit()):
|
||||
return ""
|
||||
return label
|
||||
|
||||
def _export_folder(self) -> str:
|
||||
"""The export base folder, with the active tab name appended when enabled."""
|
||||
base = self._txt_folder.text()
|
||||
if getattr(self, "_chk_tab_folder", None) and self._chk_tab_folder.isChecked():
|
||||
name = self._active_tab_name()
|
||||
if name:
|
||||
base = base.rstrip(os.sep) + "_" + name
|
||||
return base
|
||||
|
||||
def _export_base_name(self) -> str:
|
||||
return os.path.basename(self._export_folder())
|
||||
|
||||
def _on_tab_folder_toggled(self, _checked: bool = False) -> None:
|
||||
if self._file_path:
|
||||
self._refresh_markers()
|
||||
self._refresh_playlist_checks()
|
||||
self._update_next_label()
|
||||
|
||||
# ── File-list tabs ───────────────────────────────────────────
|
||||
def _add_playlist_tab(self, label: str | None = None,
|
||||
files: list[str] | None = None,
|
||||
separators: list[str] | None = None,
|
||||
select: bool = True) -> "PlaylistWidget":
|
||||
pw = PlaylistWidget()
|
||||
def _wire_pw(self, pw: "PlaylistWidget") -> None:
|
||||
pw.file_selected.connect(self._load_file)
|
||||
pw.hide_requested.connect(self._on_hide_files)
|
||||
pw.unhide_requested.connect(self._on_unhide_files)
|
||||
@@ -4425,42 +4503,129 @@ class MainWindow(QMainWindow):
|
||||
pw.disable_all_requested.connect(self._disable_all_subcats)
|
||||
pw.enable_all_requested.connect(self._enable_all_subcats)
|
||||
pw.separators_changed.connect(self._save_playlist_tabs)
|
||||
if label is None:
|
||||
label = f"List {self._playlist_tabs.count() + 1}"
|
||||
idx = self._playlist_tabs.addTab(pw, label)
|
||||
|
||||
def _add_playlist_tab(self, label: str | None = None,
|
||||
files: list[str] | None = None,
|
||||
separators: list[str] | None = None,
|
||||
select: bool = True) -> "PlaylistWidget":
|
||||
pw = PlaylistWidget()
|
||||
self._wire_pw(pw)
|
||||
pw._label = label or f"List {len(self._pws) + 1}"
|
||||
self._pws.append(pw)
|
||||
if separators:
|
||||
pw._separators_before = set(separators)
|
||||
if files:
|
||||
# Keep missing files so they're flagged in the list, not silently dropped.
|
||||
pw.add_files(files, allow_missing=True)
|
||||
if select:
|
||||
self._playlist_tabs.setCurrentIndex(idx)
|
||||
if not self._loading_tabs:
|
||||
self._refresh_layout()
|
||||
if select and not pw._pinned:
|
||||
self._playlist_tabs.setCurrentWidget(pw)
|
||||
self._active_pw = pw
|
||||
self._save_playlist_tabs()
|
||||
return pw
|
||||
|
||||
# ── Layout: tabs vs. side-by-side ────────────────────────────
|
||||
def _detach_all_pws(self) -> None:
|
||||
for pw in self._pws:
|
||||
pw.setParent(None)
|
||||
|
||||
def _clear_split_container(self) -> None:
|
||||
while self._split_layout.count():
|
||||
item = self._split_layout.takeAt(0)
|
||||
w = item.widget()
|
||||
if w is not None:
|
||||
w.deleteLater()
|
||||
|
||||
def _refresh_layout(self) -> None:
|
||||
"""Render self._pws either as tabs or, when 2+ are pinned, side-by-side."""
|
||||
pinned = [pw for pw in self._pws if pw._pinned]
|
||||
prev = self._loading_tabs
|
||||
self._loading_tabs = True
|
||||
try:
|
||||
self._detach_all_pws()
|
||||
self._playlist_tabs.clear()
|
||||
self._clear_split_container()
|
||||
if len(pinned) >= 2:
|
||||
for pw in self._pws:
|
||||
if not pw._pinned:
|
||||
self._playlist_tabs.addTab(pw, pw._label)
|
||||
splitter = QSplitter(Qt.Orientation.Horizontal)
|
||||
for pw in pinned:
|
||||
panel = QWidget()
|
||||
pl = QVBoxLayout(panel)
|
||||
pl.setContentsMargins(0, 0, 0, 0)
|
||||
pl.setSpacing(0)
|
||||
hdr = QHBoxLayout()
|
||||
lbl = QLabel(pw._label)
|
||||
lbl.setStyleSheet("font-weight: bold; padding: 2px 4px;")
|
||||
btn = QPushButton("✕")
|
||||
btn.setFixedWidth(20)
|
||||
btn.setToolTip("Remove from side-by-side")
|
||||
btn.clicked.connect(lambda _=False, w=pw: self._on_unpin(w))
|
||||
hdr.addWidget(lbl, 1)
|
||||
hdr.addWidget(btn)
|
||||
pl.addLayout(hdr)
|
||||
pl.addWidget(pw)
|
||||
splitter.addWidget(panel)
|
||||
self._split_layout.addWidget(splitter)
|
||||
self._list_stack.setCurrentWidget(self._split_container)
|
||||
else:
|
||||
for pw in self._pws:
|
||||
self._playlist_tabs.addTab(pw, pw._label)
|
||||
self._list_stack.setCurrentWidget(self._playlist_tabs)
|
||||
finally:
|
||||
self._loading_tabs = prev
|
||||
|
||||
def _on_pin_toggle(self, idx: int) -> None:
|
||||
pw = self._playlist_tabs.widget(idx)
|
||||
if pw is None:
|
||||
return
|
||||
pw._pinned = not pw._pinned
|
||||
if pw._pinned and sum(1 for w in self._pws if w._pinned) < 2:
|
||||
self._show_status("Pin another tab to show them side-by-side", 3500)
|
||||
self._refresh_layout()
|
||||
self._save_playlist_tabs()
|
||||
|
||||
def _on_unpin(self, pw: "PlaylistWidget") -> None:
|
||||
pw._pinned = False
|
||||
self._refresh_layout()
|
||||
self._save_playlist_tabs()
|
||||
|
||||
def _on_filter_changed(self, text: str) -> None:
|
||||
pw = self._playlist
|
||||
if pw is not None:
|
||||
pw.set_filter(text)
|
||||
|
||||
def _on_tab_changed(self, _idx: int) -> None:
|
||||
if self._loading_tabs or self._playlist is None:
|
||||
if self._loading_tabs:
|
||||
return
|
||||
self._playlist.set_filter(self._playlist_filter.text())
|
||||
w = self._playlist_tabs.currentWidget()
|
||||
if w is not None:
|
||||
self._active_pw = w
|
||||
w.set_filter(self._playlist_filter.text())
|
||||
self._apply_playlist_filters()
|
||||
self._save_playlist_tabs()
|
||||
|
||||
def _on_close_tab(self, idx: int) -> None:
|
||||
if self._playlist_tabs.count() <= 1:
|
||||
if len(self._pws) <= 1:
|
||||
self._show_status("Can't close the last tab", 3000)
|
||||
return
|
||||
w = self._playlist_tabs.widget(idx)
|
||||
self._playlist_tabs.removeTab(idx)
|
||||
w.deleteLater()
|
||||
pw = self._playlist_tabs.widget(idx)
|
||||
if pw is None or pw not in self._pws:
|
||||
return
|
||||
self._pws.remove(pw)
|
||||
if self._active_pw is pw:
|
||||
self._active_pw = None
|
||||
pw.setParent(None)
|
||||
pw.deleteLater()
|
||||
self._refresh_layout()
|
||||
self._save_playlist_tabs()
|
||||
|
||||
def _on_tab_renamed(self, _idx: int, _text: str) -> None:
|
||||
def _on_tab_renamed(self, idx: int, text: str) -> None:
|
||||
pw = self._playlist_tabs.widget(idx)
|
||||
if pw is not None:
|
||||
pw._label = text
|
||||
self._save_playlist_tabs()
|
||||
|
||||
def _playlist_tabs_key(self, profile: str | None = None) -> str:
|
||||
@@ -4470,26 +4635,28 @@ class MainWindow(QMainWindow):
|
||||
if self._loading_tabs:
|
||||
return
|
||||
import json
|
||||
tabs = []
|
||||
for i in range(self._playlist_tabs.count()):
|
||||
pw = self._playlist_tabs.widget(i)
|
||||
tabs.append({
|
||||
"label": self._playlist_tabs.tabText(i),
|
||||
tabs = [{
|
||||
"label": pw._label,
|
||||
"files": list(pw._paths),
|
||||
"separators": sorted(pw._separators_before),
|
||||
})
|
||||
data = {"tabs": tabs, "current": self._playlist_tabs.currentIndex()}
|
||||
"pinned": pw._pinned,
|
||||
} for pw in self._pws]
|
||||
cur = self._pws.index(self._active_pw) if self._active_pw in self._pws else 0
|
||||
data = {"tabs": tabs, "current": cur}
|
||||
self._settings.setValue(self._playlist_tabs_key(profile), json.dumps(data))
|
||||
|
||||
def _load_playlist_tabs(self, profile: str | None = None) -> None:
|
||||
"""Rebuild all file-list tabs for *profile* from settings."""
|
||||
import json
|
||||
self._loading_tabs = True
|
||||
self._active_pw = None
|
||||
try:
|
||||
while self._playlist_tabs.count():
|
||||
w = self._playlist_tabs.widget(0)
|
||||
self._playlist_tabs.removeTab(0)
|
||||
w.deleteLater()
|
||||
self._detach_all_pws()
|
||||
self._playlist_tabs.clear()
|
||||
self._clear_split_container()
|
||||
for pw in self._pws:
|
||||
pw.deleteLater()
|
||||
self._pws = []
|
||||
raw = self._settings.value(self._playlist_tabs_key(profile), "")
|
||||
data = None
|
||||
if raw:
|
||||
@@ -4497,6 +4664,7 @@ class MainWindow(QMainWindow):
|
||||
data = json.loads(raw)
|
||||
except (ValueError, TypeError):
|
||||
data = None
|
||||
cur = 0
|
||||
if not data or not data.get("tabs"):
|
||||
# Legacy fallback: one tab from old session_files/separators.
|
||||
p = profile or self._profile
|
||||
@@ -4506,20 +4674,23 @@ class MainWindow(QMainWindow):
|
||||
seps = [seps] if seps else []
|
||||
self._add_playlist_tab(
|
||||
"List 1", files=list(files),
|
||||
separators=seps, select=True)
|
||||
separators=seps, select=False)
|
||||
else:
|
||||
for t in data["tabs"]:
|
||||
self._add_playlist_tab(
|
||||
pw = self._add_playlist_tab(
|
||||
t.get("label", "List"),
|
||||
files=list(t.get("files", [])),
|
||||
separators=t.get("separators", []), select=False)
|
||||
cur = min(max(0, data.get("current", 0)),
|
||||
self._playlist_tabs.count() - 1)
|
||||
self._playlist_tabs.setCurrentIndex(cur)
|
||||
pw._pinned = bool(t.get("pinned"))
|
||||
cur = min(max(0, data.get("current", 0)), len(self._pws) - 1)
|
||||
finally:
|
||||
self._loading_tabs = False
|
||||
if self._playlist is not None:
|
||||
self._playlist.set_filter(self._playlist_filter.text())
|
||||
self._refresh_layout()
|
||||
if self._pws:
|
||||
self._active_pw = self._pws[cur]
|
||||
if not self._active_pw._pinned:
|
||||
self._playlist_tabs.setCurrentWidget(self._active_pw)
|
||||
self._active_pw.set_filter(self._playlist_filter.text())
|
||||
|
||||
def _on_profile_activated(self, index: int) -> None:
|
||||
text = self._cmb_profile.itemText(index)
|
||||
@@ -4740,6 +4911,10 @@ class MainWindow(QMainWindow):
|
||||
def _load_file(self, path: str):
|
||||
if getattr(self, "_loading_tabs", False):
|
||||
return # ignore auto-selection while rebuilding tabs
|
||||
# The list that emitted this becomes the active pane (side-by-side).
|
||||
sender = self.sender()
|
||||
if isinstance(sender, PlaylistWidget) and sender in self._pws:
|
||||
self._active_pw = sender
|
||||
if not os.path.isfile(path):
|
||||
self._show_status(f"File not found: {os.path.basename(path)}", 5000)
|
||||
return
|
||||
@@ -4821,7 +4996,7 @@ class MainWindow(QMainWindow):
|
||||
# Run DB fuzzy match off the main thread — can be slow on large databases.
|
||||
filename = os.path.basename(self._file_path)
|
||||
self._db_worker = _DBWorker(self._db, filename, self._profile,
|
||||
self._txt_folder.text())
|
||||
self._export_folder())
|
||||
self._db_worker.result.connect(self._on_db_result)
|
||||
self._db_worker.start()
|
||||
|
||||
@@ -4838,7 +5013,7 @@ class MainWindow(QMainWindow):
|
||||
|
||||
def _refresh_markers(self) -> None:
|
||||
filename = os.path.basename(self._file_path)
|
||||
folder = self._txt_folder.text()
|
||||
folder = self._export_folder()
|
||||
markers = self._db.get_markers(filename, self._profile, folder)
|
||||
self._timeline.set_markers(markers)
|
||||
others = self._db.get_other_folder_markers(
|
||||
@@ -4850,7 +5025,7 @@ class MainWindow(QMainWindow):
|
||||
self._timeline.set_other_markers({})
|
||||
return
|
||||
filename = os.path.basename(self._file_path)
|
||||
folder = self._txt_folder.text()
|
||||
folder = self._export_folder()
|
||||
others = self._db.get_other_folder_markers(
|
||||
filename, self._profile, folder)
|
||||
self._timeline.set_other_markers(others)
|
||||
@@ -4890,7 +5065,7 @@ class MainWindow(QMainWindow):
|
||||
if not deleted:
|
||||
self._db.delete_by_output_path(output_path)
|
||||
deleted = [output_path]
|
||||
folder = self._txt_folder.text()
|
||||
folder = self._export_folder()
|
||||
for path in deleted:
|
||||
if os.path.isdir(path):
|
||||
shutil.rmtree(path, ignore_errors=True)
|
||||
@@ -4920,7 +5095,7 @@ class MainWindow(QMainWindow):
|
||||
return
|
||||
filename = os.path.basename(self._file_path)
|
||||
markers = self._db.get_markers(filename, self._profile)
|
||||
folder = self._txt_folder.text()
|
||||
folder = self._export_folder()
|
||||
total_files = 0
|
||||
for _, _, output_path, _ in markers:
|
||||
group = self._db.delete_group(output_path)
|
||||
@@ -5060,7 +5235,7 @@ class MainWindow(QMainWindow):
|
||||
if reply != QMessageBox.StandardButton.Yes:
|
||||
return
|
||||
# Delete all group clips from disk
|
||||
folder = self._txt_folder.text()
|
||||
folder = self._export_folder()
|
||||
for path in all_paths:
|
||||
if os.path.isdir(path):
|
||||
shutil.rmtree(path, ignore_errors=True)
|
||||
@@ -5832,7 +6007,7 @@ class MainWindow(QMainWindow):
|
||||
)
|
||||
if reply != QMessageBox.StandardButton.Yes:
|
||||
return
|
||||
folder = self._txt_folder.text() or ""
|
||||
folder = self._export_folder() or ""
|
||||
vid_dirs: set[str] = set()
|
||||
for p in all_paths:
|
||||
if os.path.isdir(p):
|
||||
@@ -6255,7 +6430,7 @@ class MainWindow(QMainWindow):
|
||||
self._btn_auto_export.setEnabled(True)
|
||||
return
|
||||
|
||||
folder = self._txt_folder.text()
|
||||
folder = self._export_folder()
|
||||
name = self._txt_name.text() or "clip"
|
||||
fmt = self._cmb_format.currentText()
|
||||
image_sequence = fmt == "WebP sequence"
|
||||
@@ -6471,7 +6646,7 @@ class MainWindow(QMainWindow):
|
||||
)
|
||||
|
||||
def _update_next_label(self):
|
||||
folder = self._txt_folder.text()
|
||||
folder = self._export_folder()
|
||||
name = self._txt_name.text() or "clip"
|
||||
vid_name = self._get_vid_folder(folder)
|
||||
vid_folder = os.path.join(folder, vid_name)
|
||||
@@ -6511,7 +6686,7 @@ class MainWindow(QMainWindow):
|
||||
|
||||
fmt = self._cmb_format.currentText()
|
||||
image_sequence = fmt == "WebP sequence"
|
||||
folder = self._txt_folder.text()
|
||||
folder = self._export_folder()
|
||||
if folder_suffix:
|
||||
folder = folder.rstrip(os.sep) + "_" + folder_suffix
|
||||
os.makedirs(folder, exist_ok=True)
|
||||
@@ -6777,7 +6952,7 @@ class MainWindow(QMainWindow):
|
||||
if not groups:
|
||||
self._show_status("No manual exports to re-export")
|
||||
return
|
||||
folder = self._txt_folder.text()
|
||||
folder = self._export_folder()
|
||||
spread = self._spn_spread.value()
|
||||
|
||||
clip_dur = self._clip_dur
|
||||
|
||||
Reference in New Issue
Block a user