batch delete files from table and db
This commit is contained in:
parent
00d1c01e9f
commit
705407f3a3
@ -33,6 +33,9 @@ from components.AddToPlaylistWindow import AddToPlaylistWindow
|
|||||||
from components.MetadataWindow import MetadataWindow
|
from components.MetadataWindow import MetadataWindow
|
||||||
|
|
||||||
from main import Worker
|
from main import Worker
|
||||||
|
from utils.batch_delete_filepaths_from_database import (
|
||||||
|
batch_delete_filepaths_from_database,
|
||||||
|
)
|
||||||
from utils.delete_song_id_from_database import delete_song_id_from_database
|
from utils.delete_song_id_from_database import delete_song_id_from_database
|
||||||
from utils.add_files_to_library import add_files_to_library
|
from utils.add_files_to_library import add_files_to_library
|
||||||
from utils.get_reorganize_vars import get_reorganize_vars
|
from utils.get_reorganize_vars import get_reorganize_vars
|
||||||
@ -163,32 +166,31 @@ class MusicTable(QTableView):
|
|||||||
QMessageBox.Yes,
|
QMessageBox.Yes,
|
||||||
)
|
)
|
||||||
if reply:
|
if reply:
|
||||||
try:
|
|
||||||
self.model.dataChanged.disconnect(self.on_cell_data_changed)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
selected_filepaths = self.get_selected_songs_filepaths()
|
selected_filepaths = self.get_selected_songs_filepaths()
|
||||||
selected_indices = self.get_selected_rows()
|
worker = Worker(batch_delete_filepaths_from_database, selected_filepaths)
|
||||||
# FIXME: this should be batch delete with a worker thread
|
worker.signals.signal_progress.connect(self.qapp.handle_progress)
|
||||||
# probably pass selected_filepaths to a worker thread
|
worker.signals.signal_finished.connect(self.remove_selected_row_indices)
|
||||||
|
worker.signals.signal_finished.connect(self.load_music_table)
|
||||||
|
if self.qapp:
|
||||||
|
threadpool = self.qapp.threadpool
|
||||||
|
threadpool.start(worker)
|
||||||
|
|
||||||
for file in selected_filepaths:
|
def remove_selected_row_indices(self):
|
||||||
with DBA.DBAccess() as db:
|
"""Removes rows from the QTableView based on a list of indices"""
|
||||||
song_id = db.query(
|
selected_indices = self.get_selected_rows()
|
||||||
"SELECT id FROM song WHERE filepath = ?", (file,)
|
try:
|
||||||
)[0][0]
|
self.model.dataChanged.disconnect(self.on_cell_data_changed)
|
||||||
delete_song_id_from_database(song_id)
|
except Exception:
|
||||||
# This part cannot be thread...i think? bcus its Q stuff happening
|
pass
|
||||||
for index in selected_indices:
|
for index in selected_indices:
|
||||||
try:
|
|
||||||
self.model.removeRow(index)
|
|
||||||
except Exception as e:
|
|
||||||
logging.info(f" delete_songs() failed | {e}")
|
|
||||||
try:
|
try:
|
||||||
self.model.dataChanged.connect(self.on_cell_data_changed)
|
self.model.removeRow(index)
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
logging.info(f" delete_songs() failed | {e}")
|
||||||
self.load_music_table()
|
try:
|
||||||
|
self.model.dataChanged.connect(self.on_cell_data_changed)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
def open_directory(self):
|
def open_directory(self):
|
||||||
"""Opens the currently selected song in the system file manager"""
|
"""Opens the currently selected song in the system file manager"""
|
||||||
@ -358,7 +360,7 @@ class MusicTable(QTableView):
|
|||||||
worker.signals.signal_progress.connect(self.qapp.handle_progress)
|
worker.signals.signal_progress.connect(self.qapp.handle_progress)
|
||||||
self.qapp.threadpool.start(worker)
|
self.qapp.threadpool.start(worker)
|
||||||
|
|
||||||
def reorganize_selected_files(self, progress_callback):
|
def reorganize_selected_files(self, progress_callback=None):
|
||||||
"""Ctrl+Shift+R = Reorganize"""
|
"""Ctrl+Shift+R = Reorganize"""
|
||||||
filepaths = self.get_selected_songs_filepaths()
|
filepaths = self.get_selected_songs_filepaths()
|
||||||
# Confirmation screen (yes, no)
|
# Confirmation screen (yes, no)
|
||||||
@ -376,7 +378,8 @@ class MusicTable(QTableView):
|
|||||||
if str(filepath).startswith((target_dir)):
|
if str(filepath).startswith((target_dir)):
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
progress_callback.emit(filepath)
|
if progress_callback:
|
||||||
|
progress_callback.emit(f"Organizing: {filepath}")
|
||||||
# Read file metadata
|
# Read file metadata
|
||||||
artist, album = get_reorganize_vars(filepath)
|
artist, album = get_reorganize_vars(filepath)
|
||||||
# Determine the new path that needs to be made
|
# Determine the new path that needs to be made
|
||||||
|
|||||||
10
main.py
10
main.py
@ -61,11 +61,11 @@ from components import (
|
|||||||
|
|
||||||
class WorkerSignals(QObject):
|
class WorkerSignals(QObject):
|
||||||
"""
|
"""
|
||||||
How to use signals for a QRunnable class; unlike most cases where signals
|
How to use signals for a QRunnable class;
|
||||||
are defined as class attributes directly in the class, here we define a
|
Unlike most cases where signals are defined as class attributes directly in the class,
|
||||||
class that inherits from QObject and define the signals as class
|
here we define a class that inherits from QObject
|
||||||
attributes in that class. Then we can instantiate that class and use it
|
and define the signals as class attributes in that class.
|
||||||
as a signal object.
|
Then we can instantiate that class and use it as a signal object.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# 1)
|
# 1)
|
||||||
|
|||||||
@ -7,6 +7,7 @@ from .get_id3_tags import get_id3_tags
|
|||||||
from .get_reorganize_vars import get_reorganize_vars
|
from .get_reorganize_vars import get_reorganize_vars
|
||||||
from .set_id3_tag import set_id3_tag
|
from .set_id3_tag import set_id3_tag
|
||||||
from .delete_song_id_from_database import delete_song_id_from_database
|
from .delete_song_id_from_database import delete_song_id_from_database
|
||||||
|
from .batch_delete_filepaths_from_database import batch_delete_filepaths_from_database
|
||||||
from .delete_and_create_library_database import delete_and_create_library_database
|
from .delete_and_create_library_database import delete_and_create_library_database
|
||||||
from .update_song_in_database import update_song_in_database
|
from .update_song_in_database import update_song_in_database
|
||||||
from .scan_for_music import scan_for_music
|
from .scan_for_music import scan_for_music
|
||||||
|
|||||||
50
utils/batch_delete_filepaths_from_database.py
Normal file
50
utils/batch_delete_filepaths_from_database.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import DBA
|
||||||
|
from components.ErrorDialog import ErrorDialog
|
||||||
|
|
||||||
|
|
||||||
|
def batch_delete_filepaths_from_database(
|
||||||
|
files: list[str], chunk_size=1000, progress_callback=None
|
||||||
|
) -> bool:
|
||||||
|
"""
|
||||||
|
Handles deleting many songs from the database by filepath
|
||||||
|
Accounts for playlists and other song-linked tables
|
||||||
|
|
||||||
|
Returns True on success
|
||||||
|
False on failure/error
|
||||||
|
"""
|
||||||
|
# Get song IDs from filepaths
|
||||||
|
try:
|
||||||
|
with DBA.DBAccess() as db:
|
||||||
|
placeholders = ", ".join("?" for _ in files)
|
||||||
|
query = f"SELECT id FROM song WHERE filepath in ({placeholders});"
|
||||||
|
result = db.query(query, files)
|
||||||
|
song_ids = [item[0] for item in result]
|
||||||
|
except Exception as e:
|
||||||
|
dialog = ErrorDialog(
|
||||||
|
f"batch_delete_filepaths_from_database.py | An error occurred during retrieval of song_ids: {e}"
|
||||||
|
)
|
||||||
|
dialog.exec_()
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
with DBA.DBAccess() as db:
|
||||||
|
# Batch delete in chunks
|
||||||
|
for i in range(0, len(song_ids), chunk_size):
|
||||||
|
chunk = song_ids[i : i + chunk_size]
|
||||||
|
placeholders = ", ".join("?" for _ in chunk)
|
||||||
|
|
||||||
|
# Delete from playlists
|
||||||
|
query = f"DELETE FROM song_playlist WHERE song_id IN ({placeholders});"
|
||||||
|
db.execute(query, chunk)
|
||||||
|
|
||||||
|
# Delete from library
|
||||||
|
query = f"DELETE FROM song WHERE id in ({placeholders});"
|
||||||
|
db.execute(query, chunk)
|
||||||
|
if progress_callback:
|
||||||
|
progress_callback.emit(f"Deleting songs: {i}")
|
||||||
|
except Exception as e:
|
||||||
|
dialog = ErrorDialog(
|
||||||
|
f"batch_delete_filepaths_from_database.py | An error occurred during batch processing: {e}"
|
||||||
|
)
|
||||||
|
dialog.exec_()
|
||||||
|
return False
|
||||||
|
return True
|
||||||
Loading…
x
Reference in New Issue
Block a user