From 3db00fc339076b31f6233479f5594d60b40f0650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bara?= Date: Sat, 19 Mar 2011 10:22:55 +0000 Subject: [PATCH] plugin that lets you grey out deleted songs on demand ("main menu / playlist") - available by default also: this action will "ungrey" songs that were deleted but got restored SIPs --- scripts/CMakeLists.txt | 1 + scripts/invalidate-deleted/CMakeLists.txt | 5 ++++ scripts/invalidate-deleted/icon.png | Bin 0 -> 4529 bytes .../invalidate-deleted/invalidate_deleted.py | 22 ++++++++++++++++++ scripts/invalidate-deleted/script.ini | 9 +++++++ src/playlist/playlist.cpp | 15 ++++++++---- src/playlist/playlistitem.cpp | 6 +++++ src/playlist/playlistitem.h | 2 ++ src/scripting/python/playlist.sip | 3 +++ src/scripting/python/playlistitem.sip | 20 ++++++++++++++-- src/scripting/python/playlistmanager.sip | 7 ++++++ src/ui/mainwindow.ui | 3 ++- 12 files changed, 86 insertions(+), 7 deletions(-) create mode 100644 scripts/invalidate-deleted/CMakeLists.txt create mode 100644 scripts/invalidate-deleted/icon.png create mode 100644 scripts/invalidate-deleted/invalidate_deleted.py create mode 100644 scripts/invalidate-deleted/script.ini diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 7d7be4072..313b27701 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -8,3 +8,4 @@ endfunction(install_script_files) add_subdirectory(digitallyimported-radio) add_subdirectory(remove-duplicates) +add_subdirectory(invalidate-deleted) diff --git a/scripts/invalidate-deleted/CMakeLists.txt b/scripts/invalidate-deleted/CMakeLists.txt new file mode 100644 index 000000000..0b970464a --- /dev/null +++ b/scripts/invalidate-deleted/CMakeLists.txt @@ -0,0 +1,5 @@ +install_script_files(invalidate-deleted + icon.png + invalidate_deleted.py + script.ini +) diff --git a/scripts/invalidate-deleted/icon.png b/scripts/invalidate-deleted/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..158b7d54b33d81e6fcfa25063591380a50177ed9 GIT binary patch literal 4529 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 P00000NkvXXu0mjf)uFM| literal 0 HcmV?d00001 diff --git a/scripts/invalidate-deleted/invalidate_deleted.py b/scripts/invalidate-deleted/invalidate_deleted.py new file mode 100644 index 000000000..2d4e55ca6 --- /dev/null +++ b/scripts/invalidate-deleted/invalidate_deleted.py @@ -0,0 +1,22 @@ +import clementine + +from PyQt4.QtCore import QObject +from PyQt4.QtCore import SIGNAL +from PyQt4.QtGui import QAction + +class InvalidateDeleted(QObject): + + 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) + + clementine.ui.AddAction('playlist_menu', self.action) + + def grey_out_activated(self): + clementine.playlists.InvalidateDeletedSongs() + + +script = InvalidateDeleted() diff --git a/scripts/invalidate-deleted/script.ini b/scripts/invalidate-deleted/script.ini new file mode 100644 index 000000000..a1e63e20e --- /dev/null +++ b/scripts/invalidate-deleted/script.ini @@ -0,0 +1,9 @@ +[Script] +name=Deleted songs invalidator +description=This script will add a menu item for playlist's main menu which will grey out all non existent songs in all of your playlists. +author=Pawel Bara +url=http://www.clementine-player.org +icon=icon.png + +language=python +script_file=invalidate_deleted.py diff --git a/src/playlist/playlist.cpp b/src/playlist/playlist.cpp index 5bf737bc5..f4a2c25d1 100644 --- a/src/playlist/playlist.cpp +++ b/src/playlist/playlist.cpp @@ -1580,10 +1580,17 @@ void Playlist::InvalidateDeletedSongs() { PlaylistItemPtr item = items_[row]; Song song = item->Metadata(); - if(song.filetype() != Song::Type_Stream && !QFile::exists(song.filename())) { - // gray out the song if it's not there - item->SetForegroundColor(kInvalidSongPriority, kInvalidSongColor); - invalidated_rows.append(row); + if(song.filetype() != Song::Type_Stream) { + bool exists = QFile::exists(song.filename()); + + if(!exists && !item->HasForegroundColor(kInvalidSongPriority)) { + // gray out the song if it's not there + item->SetForegroundColor(kInvalidSongPriority, kInvalidSongColor); + invalidated_rows.append(row); + } else if(exists && item->HasForegroundColor(kInvalidSongPriority)) { + item->RemoveForegroundColor(kInvalidSongPriority); + invalidated_rows.append(row); + } } } diff --git a/src/playlist/playlistitem.cpp b/src/playlist/playlistitem.cpp index 4d2671be1..66f11dc0d 100644 --- a/src/playlist/playlistitem.cpp +++ b/src/playlist/playlistitem.cpp @@ -95,6 +95,9 @@ QFuture PlaylistItem::BackgroundReload() { void PlaylistItem::SetBackgroundColor(short priority, const QColor& color) { background_colors_[priority] = color; } +bool PlaylistItem::HasBackgroundColor(short priority) const { + return background_colors_.contains(priority); +} void PlaylistItem::RemoveBackgroundColor(short priority) { background_colors_.remove(priority); } @@ -110,6 +113,9 @@ bool PlaylistItem::HasCurrentBackgroundColor() const { void PlaylistItem::SetForegroundColor(short priority, const QColor& color) { foreground_colors_[priority] = color; } +bool PlaylistItem::HasForegroundColor(short priority) const { + return foreground_colors_.contains(priority); +} void PlaylistItem::RemoveForegroundColor(short priority) { foreground_colors_.remove(priority); } diff --git a/src/playlist/playlistitem.h b/src/playlist/playlistitem.h index 2f65e4de1..867f3e3dd 100644 --- a/src/playlist/playlistitem.h +++ b/src/playlist/playlistitem.h @@ -116,12 +116,14 @@ class PlaylistItem : public boost::enable_shared_from_this { // Background colors. void SetBackgroundColor(short priority, const QColor& color); + bool HasBackgroundColor(short priority) const; void RemoveBackgroundColor(short priority); QColor GetCurrentBackgroundColor() const; bool HasCurrentBackgroundColor() const; // Foreground colors. void SetForegroundColor(short priority, const QColor& color); + bool HasForegroundColor(short priority) const; void RemoveForegroundColor(short priority); QColor GetCurrentForegroundColor() const; bool HasCurrentForegroundColor() const; diff --git a/src/scripting/python/playlist.sip b/src/scripting/python/playlist.sip index 4621bfe83..10cfcbd7e 100644 --- a/src/scripting/python/playlist.sip +++ b/src/scripting/python/playlist.sip @@ -111,6 +111,9 @@ public: void InsertUrls (const QList& urls, int pos = -1, bool play_now = false, bool enqueue = false); void RemoveItemsWithoutUndo (const QList& indicesIn); + // Grays out and reloads all deleted songs in this playlist. + void InvalidateDeletedSongs(); + void StopAfter(int row); void ReloadItems(const QList& rows); diff --git a/src/scripting/python/playlistitem.sip b/src/scripting/python/playlistitem.sip index 05b355593..720436c69 100644 --- a/src/scripting/python/playlistitem.sip +++ b/src/scripting/python/playlistitem.sip @@ -199,6 +199,14 @@ Below we list all the currently taken background priorities: If it makes sense, one functionality (one plugin) can use many background priorities at the same time. +%End + + bool HasBackgroundColor(short priority) const; +%Docstring +HasBackgroundColor(priority) -> bool +Checks if this PlaylistItem has a background color with this priority set. +It doesn't need to be the current color, it just needs to exist in the colors +list. %End void RemoveBackgroundColor(short priority); @@ -231,14 +239,22 @@ If it makes sense, one functionality (one plugin) can use many foreground priorities at the same time. %End + bool HasForegroundColor(short priority) const; +%Docstring +HasForegroundColor(priority) -> bool +Checks if this PlaylistItem has a foreground color with this priority set. +It doesn't need to be the current color, it just needs to exist in the colors +list. +%End + void RemoveForegroundColor(short priority); - %Docstring +%Docstring RemoveForegroundColor(priority) Removes a foreground color with the given priority from this PlaylistItem's foreground. If there's no such color, this call will be ignored. @see: L{SetForegroundColor()} - %End +%End ~PlaylistItem(); %MethodCode diff --git a/src/scripting/python/playlistmanager.sip b/src/scripting/python/playlistmanager.sip index bd9d4da74..89a270f9c 100644 --- a/src/scripting/python/playlistmanager.sip +++ b/src/scripting/python/playlistmanager.sip @@ -85,6 +85,13 @@ Equivalent to C{playlist(active_id())}. %Docstring GetAllPlaylists() -> list of L{Playlist}s Returns a list containing all the playlists. +%End + + void InvalidateDeletedSongs(); +%Docstring +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 const QItemSelection& selection(int id) const; diff --git a/src/ui/mainwindow.ui b/src/ui/mainwindow.ui index 2b07cdbd6..88ccec92b 100644 --- a/src/ui/mainwindow.ui +++ b/src/ui/mainwindow.ui @@ -390,7 +390,7 @@ 0 0 1131 - 23 + 25 @@ -429,6 +429,7 @@ +