mirror of
https://github.com/clementine-player/Clementine
synced 2025-01-28 01:59:24 +01:00
"remove deleted songs from playlists" action in the 'deleted songs invalidator' plugin (fixes issue #1594)
This commit is contained in:
parent
90470e1315
commit
b8e1880854
@ -4,19 +4,33 @@ from PyQt4.QtCore import QObject
|
||||
from PyQt4.QtCore import SIGNAL
|
||||
from PyQt4.QtGui import QAction
|
||||
|
||||
|
||||
class InvalidateDeleted(QObject):
|
||||
"""
|
||||
TODO: actions which are defined here should be implemented here too instead of delegating
|
||||
the responsibility to Playlist Manager. Unfortunately, it cannot be done at this moment
|
||||
since using PlaylistItemPtrs in Python crashes Clementine.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
QObject.__init__(self)
|
||||
|
||||
self.action = QAction("invalidate_deleted", self)
|
||||
self.action.setText("Grey out deleted songs")
|
||||
self.connect(self.action, SIGNAL("activated()"), self.grey_out_activated)
|
||||
self.invalidate = QAction("invalidate_deleted", self)
|
||||
self.invalidate.setText("Grey out deleted songs")
|
||||
self.connect(self.invalidate, SIGNAL("activated()"), self.grey_out_activated)
|
||||
|
||||
clementine.ui.AddAction('playlist_menu', self.action)
|
||||
self.delete = QAction("remove_deleted", self)
|
||||
self.delete.setText("Remove deleted songs")
|
||||
self.connect(self.delete, SIGNAL("activated()"), self.delete_activated)
|
||||
|
||||
clementine.ui.AddAction('playlist_menu', self.invalidate)
|
||||
clementine.ui.AddAction('playlist_menu', self.delete)
|
||||
|
||||
def grey_out_activated(self):
|
||||
clementine.playlists.InvalidateDeletedSongs()
|
||||
|
||||
def delete_activated(self):
|
||||
clementine.playlists.RemoveDeletedSongs()
|
||||
|
||||
|
||||
script = InvalidateDeleted()
|
||||
|
@ -1275,6 +1275,35 @@ bool Playlist::removeRows(int row, int count, const QModelIndex& parent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Playlist::removeRows(QList<int>& rows) {
|
||||
if(rows.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// start from the end to be sure that indices won't 'move' during
|
||||
// the removal process
|
||||
qSort(rows.begin(), rows.end(), qGreater<int>());
|
||||
|
||||
QList<int> part;
|
||||
while(!rows.isEmpty()) {
|
||||
// we're splitting the input list into sequences of consecutive
|
||||
// numbers
|
||||
part.append(rows.takeFirst());
|
||||
while(rows.first() == part.last() - 1) {
|
||||
part.append(rows.takeFirst());
|
||||
}
|
||||
|
||||
// and now we're removing the current sequence
|
||||
if(!removeRows(part.last(), part.size())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
part.clear();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
PlaylistItemList Playlist::RemoveItemsWithoutUndo(int row, int count) {
|
||||
if (row < 0 || row >= items_.size() || row + count > items_.size()) {
|
||||
return PlaylistItemList();
|
||||
@ -1672,6 +1701,21 @@ void Playlist::InvalidateDeletedSongs() {
|
||||
ReloadItems(invalidated_rows);
|
||||
}
|
||||
|
||||
void Playlist::RemoveDeletedSongs() {
|
||||
QList<int> rows_to_remove;
|
||||
|
||||
for (int row = 0; row < items_.count(); ++row) {
|
||||
PlaylistItemPtr item = items_[row];
|
||||
Song song = item->Metadata();
|
||||
|
||||
if(!song.is_stream() && !QFile::exists(song.filename())) {
|
||||
rows_to_remove.append(row);
|
||||
}
|
||||
}
|
||||
|
||||
removeRows(rows_to_remove);
|
||||
}
|
||||
|
||||
bool Playlist::ApplyValidityOnCurrentSong(const QUrl& url, bool valid) {
|
||||
PlaylistItemPtr current = current_item();
|
||||
|
||||
|
@ -220,6 +220,8 @@ class Playlist : public QAbstractListModel {
|
||||
// Grays out and reloads all deleted songs in all playlists. Also, "ungreys" those songs
|
||||
// which were once deleted but now got restored somehow.
|
||||
void InvalidateDeletedSongs();
|
||||
// Removes from the playlist all local files that don't exist anymore.
|
||||
void RemoveDeletedSongs();
|
||||
|
||||
void StopAfter(int row);
|
||||
void ReloadItems(const QList<int>& rows);
|
||||
@ -305,6 +307,9 @@ class Playlist : public QAbstractListModel {
|
||||
|
||||
void RemoveItemsNotInQueue();
|
||||
|
||||
// Removes rows with given indices from this playlist.
|
||||
bool removeRows(QList<int>& rows);
|
||||
|
||||
void InformOfCurrentSongChange(const QModelIndex& top_left, const QModelIndex& bottom_right,
|
||||
const Song& metadata);
|
||||
|
||||
|
@ -348,6 +348,12 @@ void PlaylistManager::InvalidateDeletedSongs() {
|
||||
}
|
||||
}
|
||||
|
||||
void PlaylistManager::RemoveDeletedSongs() {
|
||||
foreach(Playlist* playlist, GetAllPlaylists()) {
|
||||
playlist->RemoveDeletedSongs();
|
||||
}
|
||||
}
|
||||
|
||||
QString PlaylistManager::GetNameForNewPlaylist(const SongList& songs) {
|
||||
if (songs.isEmpty()) {
|
||||
return tr("Playlist");
|
||||
|
@ -54,6 +54,8 @@ public:
|
||||
virtual QList<Playlist*> GetAllPlaylists() const = 0;
|
||||
// Grays out and reloads all deleted songs in all playlists.
|
||||
virtual void InvalidateDeletedSongs() = 0;
|
||||
// Removes all deleted songs from all playlists.
|
||||
virtual void RemoveDeletedSongs() = 0;
|
||||
|
||||
virtual const QItemSelection& selection(int id) const = 0;
|
||||
virtual const QItemSelection& current_selection() const = 0;
|
||||
@ -137,6 +139,8 @@ public:
|
||||
QList<Playlist*> GetAllPlaylists() const;
|
||||
// Grays out and reloads all deleted songs in all playlists.
|
||||
void InvalidateDeletedSongs();
|
||||
// Removes all deleted songs from all playlists.
|
||||
void RemoveDeletedSongs();
|
||||
|
||||
// Returns a pretty automatic name for playlist created from the given list of
|
||||
// songs.
|
||||
|
@ -92,6 +92,12 @@ Returns a list containing all the playlists.
|
||||
InvalidateDeletedSongs()
|
||||
Grays out and reloads all deleted songs in all playlists. Also, "ungreys"
|
||||
those songs which were once deleted but now got restored somehow.
|
||||
%End
|
||||
|
||||
void RemoveDeletedSongs();
|
||||
%Docstring
|
||||
RemoveDeletedSongs()
|
||||
Removes all deleted songs from all playlists.
|
||||
%End
|
||||
|
||||
const QItemSelection& selection(int id) const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user