Add Ctrl-X cut and paste-above-selection

Cut (Ctrl-X) marks the selection on the clipboard with a `cut` flag; a
paste of a cut from a real playlist is a *move* (single-undo across
playlists via move_tracks_between_playlists; same-playlist reorders),
while a copy — or a cut from the library, which has nothing to remove —
just adds. Paste now inserts *above the selected track* rather than
appending. Cut/Paste added to the track context menu; parse_tracks_mime
now tolerates a None/empty clipboard.
This commit is contained in:
2026-06-26 21:55:38 -04:00
parent dcbd288b31
commit d1db60c057
6 changed files with 235 additions and 9 deletions
+33
View File
@@ -234,6 +234,39 @@ class LibraryManager(QObject):
self._set_track_ids(pid, after)
self._push_track_ids("Reorder Playlist", pid, before, after)
def move_tracks_between_playlists(self, src_pid: str, src_rows: list[int],
dest_pid: str, dest_position: int | None = None):
"""Cut tracks out of one playlist and insert them into another as a
single undoable move (Ctrl-X / Ctrl-V across playlists). For the same
playlist, use move_tracks_in_playlist instead."""
src = self.library.playlists.get(src_pid)
dest = self.library.playlists.get(dest_pid)
if (not src or not dest or src_pid == dest_pid
or dest.playlist_type == PlaylistType.FOLDER):
return
src_before = list(src.track_ids)
dest_before = list(dest.track_ids)
rows = sorted(set(r for r in src_rows if 0 <= r < len(src_before)))
if not rows:
return
moving = [src_before[r] for r in rows]
src_after = [tid for i, tid in enumerate(src_before) if i not in rows]
dest_after = list(dest_before)
if dest_position is None or dest_position >= len(dest_after):
dest_after.extend(moving)
else:
dest_after[dest_position:dest_position] = moving
def apply(src_ids, dest_ids):
self._set_track_ids(src_pid, src_ids)
self._set_track_ids(dest_pid, dest_ids)
apply(src_after, dest_after)
self.undo_stack.push(Command(
"Move to Playlist",
undo=lambda: apply(src_before, dest_before),
redo=lambda: apply(src_after, dest_after)))
def _set_track_ids(self, pid: str, ids: list[int]):
playlist = self.library.playlists.get(pid)
if playlist is None: