diff --git a/src/main.py b/src/main.py index 075b403..233f842 100644 --- a/src/main.py +++ b/src/main.py @@ -216,6 +216,7 @@ class MainWindow(QMainWindow): self.worker_thread = None self.downloaded_tracks: List[TrackInfo] = [] self.library_ready: List[Dict] = [] + self.library_source_files: List[str] = [] self.ipod_devices: List[Dict] = [] self.current_mount_point: Optional[str] = None @@ -560,15 +561,54 @@ class MainWindow(QMainWindow): self.library_status.setText("No tracks ready — convert source files or download") self.library_transfer_btn.setEnabled(False) - def _refresh_source_ui(self, sources): + def _refresh_source_ui(self, scanned_sources): + """Build the Source Files list by combining scanned files + manual additions. + + Deduplicates by path. All items get UserRole data for _get_selected_source_files(). + """ self.library_source_list.clear() - for src in sorted(sources, key=lambda s: (s["artist"], s["title"])): + + seen_paths = set() + all_sources = [] + + for src in scanned_sources: + path = src.get("path", "") + if path and path not in seen_paths and os.path.exists(path): + seen_paths.add(path) + all_sources.append(src) + + for fpath in self.library_source_files: + if fpath in seen_paths: + continue + if not os.path.exists(fpath): + continue + fname = os.path.basename(fpath) + size = os.path.getsize(fpath) + try: + handler = MetadataHandler() + info = handler.extract_tags(fpath) + title = info.title if info else fname + artist = info.artist if info else "Unknown" + except Exception: + title = fname + artist = "Unknown" + + src = { + "path": fpath, + "title": title, + "artist": artist, + "size": size, + } + all_sources.append(src) + seen_paths.add(fpath) + + for src in sorted(all_sources, key=lambda s: (s["artist"], s["title"])): display = f"{src['artist']} — {src['title']} {self._format_size(src['size'])}" item = QListWidgetItem(display) item.setData(Qt.ItemDataRole.UserRole, src) self.library_source_list.addItem(item) - count = len(sources) + count = len(all_sources) if count: self.library_convert_btn.setEnabled(True) else: @@ -620,15 +660,19 @@ class MainWindow(QMainWindow): self._scan_library() def _on_library_add_files(self): - audio_filter = "Audio Files (*.flac *.wav *.ogg *.opus *.wma *.ape *.aiff *.alac)" + source_filter = "Audio Files (*.flac *.wav *.ogg *.opus *.wma *.ape *.aiff *.alac)" files, _ = QFileDialog.getOpenFileNames( - self, "Select Audio Files", "", audio_filter + self, "Select Audio Files", "", source_filter ) + new_files = [] for f in files: - existing = self.library_source_list.findItems(f, Qt.MatchFlag.MatchExactly) - if not existing: - self.library_source_list.addItem(f) - self._scan_library() + ext = os.path.splitext(f)[1].lower() + if ext in SOURCE_EXTS and os.path.exists(f) and f not in self.library_source_files: + self.library_source_files.append(f) + new_files.append(f) + + if new_files: + self._refresh_source_ui([]) def _on_library_remove_selected(self): """Delete selected files from disk and clean up empty directories.""" @@ -666,6 +710,8 @@ class MainWindow(QMainWindow): try: os.remove(path) deleted += 1 + if path in self.library_source_files: + self.library_source_files.remove(path) parent = os.path.dirname(path) while parent != os.path.dirname(parent): if os.listdir(parent):