Add the ability to remove tracks from Spotify playlists
This commit is contained in:
parent
af11f5551d
commit
f81fa2d119
|
@ -298,6 +298,8 @@ void SpotifyClient::MessageArrived(const pb::spotify::Message& message) {
|
|||
SetPaused(message.pause_request());
|
||||
} else if (message.has_add_tracks_to_playlist()) {
|
||||
AddTracksToPlaylist(message.add_tracks_to_playlist());
|
||||
} else if (message.has_remove_tracks_from_playlist()) {
|
||||
RemoveTracksFromPlaylist(message.remove_tracks_from_playlist());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -639,6 +641,31 @@ void SpotifyClient::AddTracksToPlaylist(
|
|||
}
|
||||
}
|
||||
|
||||
void SpotifyClient::RemoveTracksFromPlaylist(
|
||||
const pb::spotify::RemoveTracksFromPlaylistRequest& req) {
|
||||
|
||||
// Get the playlist we want to update
|
||||
int playlist_index = req.playlist_index();
|
||||
sp_playlist* playlist =
|
||||
GetPlaylist(pb::spotify::UserPlaylist, playlist_index);
|
||||
if (!playlist) {
|
||||
qLog(Error) << "Playlist " << playlist_index << "not found";
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the position of the tracks we want to remove
|
||||
std::unique_ptr<int[]> tracks_indices_array (new int[req.track_index_size()]);
|
||||
for (int i = 0; i < req.track_index_size(); ++i) {
|
||||
tracks_indices_array[i] = req.track_index(i);
|
||||
}
|
||||
|
||||
if (sp_playlist_remove_tracks(playlist, tracks_indices_array.get(),
|
||||
req.track_index_size()) != SP_ERROR_OK) {
|
||||
qLog(Error) << "Error when removing tracks!";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SpotifyClient::ConvertTrack(sp_track* track, pb::spotify::Track* pb) {
|
||||
sp_album* album = sp_track_album(track);
|
||||
|
||||
|
|
|
@ -124,6 +124,7 @@ class SpotifyClient : public AbstractMessageHandler<pb::spotify::Message> {
|
|||
void LoadPlaylist(const pb::spotify::LoadPlaylistRequest& req);
|
||||
void SyncPlaylist(const pb::spotify::SyncPlaylistRequest& req);
|
||||
void AddTracksToPlaylist(const pb::spotify::AddTracksToPlaylistRequest& req);
|
||||
void RemoveTracksFromPlaylist(const pb::spotify::RemoveTracksFromPlaylistRequest& req);
|
||||
void StartPlayback(const pb::spotify::PlaybackRequest& req);
|
||||
void Seek(qint64 offset_nsec);
|
||||
void LoadImage(const QString& id_b64);
|
||||
|
|
|
@ -199,7 +199,12 @@ message AddTracksToPlaylistRequest {
|
|||
repeated string track_uri = 2;
|
||||
}
|
||||
|
||||
// NEXT_ID: 24
|
||||
message RemoveTracksFromPlaylistRequest {
|
||||
required int64 playlist_index = 1;
|
||||
repeated int64 track_index = 2;
|
||||
}
|
||||
|
||||
// NEXT_ID: 25
|
||||
message Message {
|
||||
// Not currently used
|
||||
optional int32 id = 18;
|
||||
|
@ -226,4 +231,5 @@ message Message {
|
|||
optional PauseRequest pause_request = 21;
|
||||
optional SeekCompleted seek_completed = 22;
|
||||
optional AddTracksToPlaylistRequest add_tracks_to_playlist = 23;
|
||||
optional RemoveTracksFromPlaylistRequest remove_tracks_from_playlist = 24;
|
||||
}
|
||||
|
|
|
@ -219,6 +219,18 @@ void SpotifyServer::AddSongsToPlaylist(int playlist_index,
|
|||
SendOrQueueMessage(message);
|
||||
}
|
||||
|
||||
void SpotifyServer::RemoveSongsFromPlaylist(
|
||||
int playlist_index, const QList<int>& songs_indices_to_remove) {
|
||||
pb::spotify::Message message;
|
||||
pb::spotify::RemoveTracksFromPlaylistRequest* req =
|
||||
message.mutable_remove_tracks_from_playlist();
|
||||
req->set_playlist_index(playlist_index);
|
||||
for (int song_index : songs_indices_to_remove) {
|
||||
req->add_track_index(song_index);
|
||||
}
|
||||
SendOrQueueMessage(message);
|
||||
}
|
||||
|
||||
void SpotifyServer::StartPlaybackLater(const QString& uri, quint16 port) {
|
||||
QTimer* timer = new QTimer(this);
|
||||
connect(timer, SIGNAL(timeout()), timer, SLOT(deleteLater()));
|
||||
|
|
|
@ -44,6 +44,8 @@ class SpotifyServer : public AbstractMessageHandler<pb::spotify::Message> {
|
|||
void LoadUserPlaylist(int index);
|
||||
void SyncUserPlaylist(int index);
|
||||
void AddSongsToPlaylist(int playlist_index, const QList<QUrl>& songs_urls);
|
||||
void RemoveSongsFromPlaylist(int playlist_index,
|
||||
const QList<int>& songs_indices_to_remove);
|
||||
void StartPlaybackLater(const QString& uri, quint16 port);
|
||||
void Search(const QString& text, int limit, int limit_album = 0);
|
||||
void LoadImage(const QString& id);
|
||||
|
|
|
@ -53,6 +53,10 @@ SpotifyService::SpotifyService(Application* app, InternetModel* parent)
|
|||
toplist_(nullptr),
|
||||
login_task_id_(0),
|
||||
context_menu_(nullptr),
|
||||
playlist_context_menu_(nullptr),
|
||||
song_context_menu_(nullptr),
|
||||
playlist_sync_action_(nullptr),
|
||||
remove_from_playlist_(nullptr),
|
||||
search_box_(new SearchBoxWidget(this)),
|
||||
search_delay_(new QTimer(this)),
|
||||
login_state_(LoginState_OtherError),
|
||||
|
@ -590,9 +594,7 @@ void SpotifyService::EnsureMenuCreated() {
|
|||
if (context_menu_) return;
|
||||
|
||||
context_menu_ = new QMenu;
|
||||
context_menu_->addAction(IconLoader::Load("configure"),
|
||||
tr("Configure Spotify..."), this,
|
||||
SLOT(ShowConfig()));
|
||||
context_menu_->addAction(GetNewShowConfigAction());
|
||||
|
||||
playlist_context_menu_ = new QMenu;
|
||||
playlist_context_menu_->addActions(GetPlaylistActions());
|
||||
|
@ -601,9 +603,15 @@ void SpotifyService::EnsureMenuCreated() {
|
|||
IconLoader::Load("view-refresh"), tr("Make playlist available offline"),
|
||||
this, SLOT(SyncPlaylist()));
|
||||
playlist_context_menu_->addSeparator();
|
||||
playlist_context_menu_->addAction(IconLoader::Load("configure"),
|
||||
tr("Configure Spotify..."), this,
|
||||
SLOT(ShowConfig()));
|
||||
playlist_context_menu_->addAction(GetNewShowConfigAction());
|
||||
|
||||
song_context_menu_ = new QMenu;
|
||||
remove_from_playlist_ = song_context_menu_->addAction(
|
||||
IconLoader::Load("list-remove"),
|
||||
tr("Remove from playlist"), this,
|
||||
SLOT(RemoveCurrentFromPlaylist()));
|
||||
|
||||
song_context_menu_->addAction(GetNewShowConfigAction());
|
||||
}
|
||||
|
||||
void SpotifyService::ClearSearchResults() {
|
||||
|
@ -728,6 +736,14 @@ void SpotifyService::ShowContextMenu(const QPoint& global_pos) {
|
|||
playlist_sync_action_->setData(qVariantFromValue(item));
|
||||
playlist_context_menu_->popup(global_pos);
|
||||
return;
|
||||
} else if (type == InternetModel::Type_Track) {
|
||||
// Is this track contained in a playlist we can modify?
|
||||
bool is_playlist_modifiable = item->parent() &&
|
||||
item->parent()->data(Role_UserPlaylistIsMine).toBool();
|
||||
remove_from_playlist_->setVisible(is_playlist_modifiable);
|
||||
|
||||
song_context_menu_->popup(global_pos);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -791,10 +807,49 @@ void SpotifyService::SyncPlaylistProgress(
|
|||
}
|
||||
}
|
||||
|
||||
QAction* SpotifyService::GetNewShowConfigAction() {
|
||||
QAction* action = new QAction(
|
||||
IconLoader::Load("configure"),
|
||||
tr("Configure Spotify..."), this);
|
||||
connect(action, SIGNAL(triggered()), this, SLOT(ShowConfig()));
|
||||
return action;
|
||||
}
|
||||
|
||||
void SpotifyService::ShowConfig() {
|
||||
app_->OpenSettingsDialogAtPage(SettingsDialog::Page_Spotify);
|
||||
}
|
||||
|
||||
void SpotifyService::RemoveCurrentFromPlaylist() {
|
||||
const QModelIndexList& indexes(model()->selected_indexes());
|
||||
QMap<int, QList<int> > playlists_songs_indices;
|
||||
for (const QModelIndex& index : indexes) {
|
||||
if (index.parent().data(InternetModel::Role_Type).toInt() !=
|
||||
InternetModel::Type_UserPlaylist) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (index.data(InternetModel::Role_Type).toInt() != InternetModel::Type_Track) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int playlist_index = index.parent().data(Role_UserPlaylistIndex).toInt();
|
||||
int song_index = index.row();
|
||||
playlists_songs_indices[playlist_index] << song_index;
|
||||
}
|
||||
|
||||
for (QMap<int, QList<int> >::const_iterator it =
|
||||
playlists_songs_indices.constBegin();
|
||||
it != playlists_songs_indices.constEnd(); ++it) {
|
||||
RemoveSongsFromPlaylist(it.key(), it.value());
|
||||
}
|
||||
}
|
||||
|
||||
void SpotifyService::RemoveSongsFromPlaylist(
|
||||
int playlist_index, const QList<int>& songs_indices_to_remove) {
|
||||
|
||||
server_->RemoveSongsFromPlaylist(playlist_index, songs_indices_to_remove);
|
||||
}
|
||||
|
||||
void SpotifyService::Logout() {
|
||||
delete server_;
|
||||
delete blob_process_;
|
||||
|
|
|
@ -25,7 +25,6 @@ class SpotifyService : public InternetService {
|
|||
Type_SearchResults = InternetModel::TypeCount,
|
||||
Type_StarredPlaylist,
|
||||
Type_InboxPlaylist,
|
||||
Type_Track,
|
||||
Type_Toplist,
|
||||
};
|
||||
|
||||
|
@ -84,6 +83,7 @@ signals:
|
|||
public slots:
|
||||
void Search(const QString& text, bool now = false);
|
||||
void ShowConfig();
|
||||
void RemoveCurrentFromPlaylist();
|
||||
|
||||
private:
|
||||
void StartBlobProcess();
|
||||
|
@ -94,6 +94,10 @@ signals:
|
|||
const pb::spotify::LoadPlaylistResponse& response);
|
||||
void AddSongsToPlaylist(int playlist_index, const QList<QUrl>& songs_urls);
|
||||
void EnsureMenuCreated();
|
||||
// Create a new "show config" action. The caller is responsible for deleting
|
||||
// the pointer (or adding it to menu or anything else that will take ownership
|
||||
// of it)
|
||||
QAction* GetNewShowConfigAction();
|
||||
void ClearSearchResults();
|
||||
|
||||
QStandardItem* PlaylistBySpotifyIndex(int index) const;
|
||||
|
@ -106,6 +110,8 @@ signals:
|
|||
void LoginCompleted(bool success, const QString& error,
|
||||
pb::spotify::LoginResponse_Error error_code);
|
||||
void AddCurrentSongToPlaylist(QAction* action);
|
||||
void RemoveSongsFromPlaylist(int playlist_index,
|
||||
const QList<int>& songs_indices_to_remove);
|
||||
void PlaylistsUpdated(const pb::spotify::Playlists& response);
|
||||
void InboxLoaded(const pb::spotify::LoadPlaylistResponse& response);
|
||||
void StarredLoaded(const pb::spotify::LoadPlaylistResponse& response);
|
||||
|
@ -139,8 +145,10 @@ signals:
|
|||
|
||||
QMenu* context_menu_;
|
||||
QMenu* playlist_context_menu_;
|
||||
QMenu* song_context_menu_;
|
||||
QAction* playlist_sync_action_;
|
||||
QList<QAction*> playlistitem_actions_;
|
||||
QAction* remove_from_playlist_;
|
||||
QUrl current_song_url_;
|
||||
|
||||
SearchBoxWidget* search_box_;
|
||||
|
|
Loading…
Reference in New Issue