File drops from the file manager insert at the drop position
The table already computed and emitted the drop row for external URL drops, but PlaylistView._on_files_dropped threw it away, so imported files always appended. Thread it through: playlist_view.files_dropped gains a row slot (None = append), MainWindow.import_files and file_importer.import_paths take an optional position and hand it to add_tracks_to_playlist, which already supported positional insert. Files already in the library dedup to the existing track and insert at the drop position without duplicating the library entry.
This commit is contained in:
@@ -314,16 +314,18 @@ class MainWindow(QMainWindow):
|
||||
if paths:
|
||||
self.import_files([Path(p) for p in paths])
|
||||
|
||||
def import_files(self, paths, playlist_pid: str = ""):
|
||||
def import_files(self, paths, playlist_pid: str = "",
|
||||
position: int | None = None):
|
||||
self.statusBar().showMessage(f"Importing {len(paths)} item(s)…")
|
||||
imported = file_importer.import_paths(
|
||||
paths, self._music_import_dir(), self._manager, playlist_pid)
|
||||
paths, self._music_import_dir(), self._manager, playlist_pid,
|
||||
position)
|
||||
self.statusBar().showMessage(f"Imported {len(imported)} track(s)", 5000)
|
||||
if imported:
|
||||
self._library_view.reload()
|
||||
|
||||
def _import_files_to_playlist(self, paths, pid):
|
||||
self.import_files([Path(p) for p in paths], pid)
|
||||
def _import_files_to_playlist(self, paths, pid, position=None):
|
||||
self.import_files([Path(p) for p in paths], pid, position)
|
||||
|
||||
# ---- album art download ----
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ from lintunes.gui.playlist_ops import add_tracks_with_dup_check
|
||||
class PlaylistView(TableSettingsMixin, QWidget):
|
||||
play_requested = pyqtSignal(list, int)
|
||||
info_requested = pyqtSignal(list)
|
||||
files_dropped = pyqtSignal(list, str) # paths, playlist pid
|
||||
files_dropped = pyqtSignal(list, str, object) # paths, pid, row or None
|
||||
show_in_playlist_requested = pyqtSignal(int, str) # track_id, playlist pid
|
||||
|
||||
def __init__(self, manager, parent=None):
|
||||
@@ -124,7 +124,8 @@ class PlaylistView(TableSettingsMixin, QWidget):
|
||||
|
||||
def _on_files_dropped(self, paths, drop_row):
|
||||
if self._editable():
|
||||
self.files_dropped.emit(paths, self._playlist.persistent_id)
|
||||
self.files_dropped.emit(
|
||||
paths, self._playlist.persistent_id, drop_row)
|
||||
|
||||
def _on_remove(self, rows):
|
||||
if self._editable():
|
||||
|
||||
@@ -97,8 +97,10 @@ def import_file(source: Path, music_dir: Path, manager,
|
||||
|
||||
|
||||
def import_paths(paths: list[Path], music_dir: Path, manager,
|
||||
playlist_pid: str = "") -> list[Track]:
|
||||
"""Import files and directories (recursively); optionally add to a playlist."""
|
||||
playlist_pid: str = "",
|
||||
position: int | None = None) -> list[Track]:
|
||||
"""Import files and directories (recursively); optionally add to a
|
||||
playlist, inserting at `position` (None = append)."""
|
||||
files: list[Path] = []
|
||||
for path in paths:
|
||||
path = Path(path)
|
||||
@@ -119,5 +121,6 @@ def import_paths(paths: list[Path], music_dir: Path, manager,
|
||||
imported.append(track)
|
||||
|
||||
if playlist_pid and imported:
|
||||
manager.add_tracks_to_playlist(playlist_pid, [t.track_id for t in imported])
|
||||
manager.add_tracks_to_playlist(
|
||||
playlist_pid, [t.track_id for t in imported], position)
|
||||
return imported
|
||||
|
||||
@@ -99,3 +99,75 @@ class TestVisualizerGrayColor:
|
||||
def test_visualizer_row_in_preferences_dialog(self, qapp):
|
||||
from lintunes.gui.preferences_dialog import _COLOR_ROWS
|
||||
assert "color_visualizer_gray" in [key for key, _label in _COLOR_ROWS]
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 2. External file drops insert at the drop position
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
def _seeded_manager(tmp_path, track_ids=(1, 2, 3)):
|
||||
from lintunes.models import Library, Track
|
||||
from lintunes.library_manager import LibraryManager
|
||||
tracks = {tid: Track(track_id=tid, name=f"T{tid}") for tid in track_ids}
|
||||
return LibraryManager(Library(tracks=tracks), tmp_path / "data")
|
||||
|
||||
|
||||
class TestFileDropPosition:
|
||||
def test_import_paths_inserts_at_position(self, qapp, tmp_path, mp3_file):
|
||||
from lintunes.importers import file_importer
|
||||
manager = _seeded_manager(tmp_path)
|
||||
playlist = manager.create_playlist("Drops")
|
||||
manager.add_tracks_to_playlist(playlist.persistent_id, [1, 2, 3])
|
||||
|
||||
imported = file_importer.import_paths(
|
||||
[mp3_file], tmp_path / "music", manager,
|
||||
playlist.persistent_id, position=1)
|
||||
|
||||
assert len(imported) == 1
|
||||
new_id = imported[0].track_id
|
||||
assert playlist.track_ids == [1, new_id, 2, 3]
|
||||
|
||||
def test_import_paths_default_appends(self, qapp, tmp_path, mp3_file):
|
||||
from lintunes.importers import file_importer
|
||||
manager = _seeded_manager(tmp_path)
|
||||
playlist = manager.create_playlist("Drops")
|
||||
manager.add_tracks_to_playlist(playlist.persistent_id, [1, 2])
|
||||
|
||||
imported = file_importer.import_paths(
|
||||
[mp3_file], tmp_path / "music", manager, playlist.persistent_id)
|
||||
|
||||
assert playlist.track_ids == [1, 2, imported[0].track_id]
|
||||
|
||||
def test_duplicate_file_inserts_without_new_track(self, qapp, tmp_path,
|
||||
mp3_file):
|
||||
from lintunes.importers import file_importer
|
||||
manager = _seeded_manager(tmp_path)
|
||||
existing = file_importer.import_file(
|
||||
mp3_file, tmp_path / "music", manager)
|
||||
playlist = manager.create_playlist("Drops")
|
||||
manager.add_tracks_to_playlist(playlist.persistent_id, [1, 2])
|
||||
count_before = len(manager.library.tracks)
|
||||
|
||||
imported = file_importer.import_paths(
|
||||
[mp3_file], tmp_path / "music", manager,
|
||||
playlist.persistent_id, position=0)
|
||||
|
||||
assert imported[0].track_id == existing.track_id
|
||||
assert playlist.track_ids == [existing.track_id, 1, 2]
|
||||
assert len(manager.library.tracks) == count_before
|
||||
|
||||
def test_playlist_view_relays_drop_row(self, qapp, tmp_path):
|
||||
from lintunes.gui.playlist_view import PlaylistView
|
||||
manager = _seeded_manager(tmp_path)
|
||||
playlist = manager.create_playlist("Drops")
|
||||
view = PlaylistView(manager)
|
||||
view.show_playlist(playlist)
|
||||
received = []
|
||||
view.files_dropped.connect(
|
||||
lambda paths, pid, row: received.append((paths, pid, row)))
|
||||
|
||||
view._on_files_dropped(["/x.mp3"], 2)
|
||||
view._on_files_dropped(["/y.mp3"], None)
|
||||
|
||||
assert received == [(["/x.mp3"], playlist.persistent_id, 2),
|
||||
(["/y.mp3"], playlist.persistent_id, None)]
|
||||
|
||||
Reference in New Issue
Block a user