diff --git a/src/podcasts/podcastbackend.cpp b/src/podcasts/podcastbackend.cpp index 7aace691d..e4a5a7fda 100644 --- a/src/podcasts/podcastbackend.cpp +++ b/src/podcasts/podcastbackend.cpp @@ -18,13 +18,14 @@ */ #include "podcastbackend.h" + +#include + #include "core/application.h" #include "core/database.h" #include "core/logging.h" #include "core/scopedtransaction.h" -#include - PodcastBackend::PodcastBackend(Application* app, QObject* parent) : QObject(parent), app_(app), db_(app->database()) {} diff --git a/src/podcasts/podcastdeleter.cpp b/src/podcasts/podcastdeleter.cpp index 611f2d94f..11f35b037 100644 --- a/src/podcasts/podcastdeleter.cpp +++ b/src/podcasts/podcastdeleter.cpp @@ -15,13 +15,6 @@ along with Clementine. If not, see . */ -#include "core/application.h" -#include "core/logging.h" -#include "core/timeconstants.h" -#include "core/utilities.h" -#include "library/librarydirectorymodel.h" -#include "library/librarymodel.h" -#include "podcastbackend.h" #include "podcastdeleter.h" #include @@ -31,6 +24,14 @@ #include #include +#include "core/application.h" +#include "core/logging.h" +#include "core/timeconstants.h" +#include "core/utilities.h" +#include "library/librarydirectorymodel.h" +#include "library/librarymodel.h" +#include "podcastbackend.h" + const char* PodcastDeleter::kSettingsGroup = "Podcasts"; const int PodcastDeleter::kAutoDeleteCheckIntervalMsec = 60 * 6 * 60 * kMsecPerSec; @@ -76,7 +77,7 @@ void PodcastDeleter::AutoDelete() { } auto_delete_timer_->stop(); QDateTime max_date = QDateTime::currentDateTime(); - qint64 time_out; + qint64 timeout_ms; PodcastEpisode oldest_episode; QDateTime oldest_episode_time; max_date = max_date.addSecs(-delete_after_secs_); @@ -99,11 +100,11 @@ void PodcastDeleter::AutoDelete() { oldest_episode_time = oldest_episode.listened_date(); } - time_out = QDateTime::currentDateTime().toMSecsSinceEpoch(); - time_out -= oldest_episode_time.toMSecsSinceEpoch(); - time_out = (delete_after_secs_ * kMsecPerSec) - time_out; - if (time_out >= 0) { - auto_delete_timer_->setInterval(time_out); + timeout_ms = QDateTime::currentDateTime().toMSecsSinceEpoch(); + timeout_ms -= oldest_episode_time.toMSecsSinceEpoch(); + timeout_ms = (delete_after_secs_ * kMsecPerSec) - timeout_ms; + if (timeout_ms >= 0) { + auto_delete_timer_->setInterval(timeout_ms); } else { auto_delete_timer_->setInterval(kAutoDeleteCheckIntervalMsec); } diff --git a/src/podcasts/podcastdownloader.cpp b/src/podcasts/podcastdownloader.cpp index 8d42f4741..3be213628 100644 --- a/src/podcasts/podcastdownloader.cpp +++ b/src/podcasts/podcastdownloader.cpp @@ -47,11 +47,11 @@ Task::Task(PodcastEpisode episode, QFile* file, PodcastBackend* backend) connect(repl.get(), SIGNAL(readyRead()), SLOT(reading())); connect(repl.get(), SIGNAL(finished()), SLOT(finishedInternal())); connect(repl.get(), SIGNAL(downloadProgress(qint64, qint64)), - SLOT(downloadProgress_(qint64, qint64))); + SLOT(downloadProgressInternal(qint64, qint64))); emit ProgressChanged(episode_, PodcastDownload::Downloading, 0); } -const PodcastEpisode Task::episode() { return episode_; } +PodcastEpisode Task::episode() const { return episode_; } void Task::reading() { qint64 bytes = 0; @@ -62,6 +62,15 @@ void Task::reading() { file_->write(repl->reply()->read(bytes)); } } +void Task::finishedPublic() { + disconnect(repl.get(), SIGNAL(readyRead()), 0, 0); + disconnect(repl.get(), SIGNAL(downloadProgress(qint64, qint64)), 0, 0); + disconnect(repl.get(), SIGNAL(finished()), 0, 0); + emit ProgressChanged(episode_, PodcastDownload::NotDownloading, 0); + // Delete the file + file_->remove(); + emit finished(); +} void Task::finishedInternal() { if (repl->error() != QNetworkReply::NoError) { @@ -86,13 +95,13 @@ void Task::finishedInternal() { Song song = episode_.ToSong(podcast); emit ProgressChanged(episode_, PodcastDownload::Finished, 0); - emit finished(); // I didn't ecountered even a single podcast with a corect metadata TagReaderClient::Instance()->SaveFileBlocking(file_->fileName(), song); + emit finished(); } -void Task::downloadProgress_(qint64 received, qint64 total) { +void Task::downloadProgressInternal(qint64 received, qint64 total) { if (total <= 0) { emit ProgressChanged(episode_, PodcastDownload::Downloading, 0); } else { @@ -208,6 +217,7 @@ void PodcastDownloader::DownloadEpisode(const PodcastEpisode& episode) { void PodcastDownloader::ReplyFinished() { Task* task = qobject_cast(sender()); list_tasks_.removeAll(task); + delete task; } QString PodcastDownloader::SanitiseFilenameComponent(const QString& text) @@ -228,3 +238,30 @@ void PodcastDownloader::EpisodesAdded(const PodcastEpisodeList& episodes) { } } } + +PodcastEpisodeList PodcastDownloader::EpisodesDownloading(const PodcastEpisodeList& episodes) { + PodcastEpisodeList ret; + for (Task* tas : list_tasks_) { + for (PodcastEpisode episode : episodes) { + if (tas->episode().database_id() == episode.database_id()) { + ret << episode; + } + } + } + return ret; +} + +void PodcastDownloader::cancelDownload(const PodcastEpisodeList& episodes) { + QList ta; + for (Task* tas : list_tasks_) { + for (PodcastEpisode episode : episodes) { + if (tas->episode().database_id() == episode.database_id()) { + ta << tas; + } + } + } + for (Task* tas : ta) { + tas->finishedPublic(); + list_tasks_.removeAll(tas); + } +} diff --git a/src/podcasts/podcastdownloader.h b/src/podcasts/podcastdownloader.h index cfdb4044a..4f3e2c3dd 100644 --- a/src/podcasts/podcastdownloader.h +++ b/src/podcasts/podcastdownloader.h @@ -52,17 +52,20 @@ class Task : public QObject { public: Task(PodcastEpisode episode, QFile* file, PodcastBackend* backend); - const PodcastEpisode episode(); + PodcastEpisode episode() const; signals: void ProgressChanged(const PodcastEpisode& episode, PodcastDownload::State state, int percent); void finished(); + public slots: + void finishedPublic(); + private slots: void reading(); + void downloadProgressInternal(qint64 received, qint64 total); void finishedInternal(); - void downloadProgress_(qint64 received, qint64 total); private: std::unique_ptr file_; @@ -80,12 +83,13 @@ class PodcastDownloader : public QObject { explicit PodcastDownloader(Application* app, QObject* parent = nullptr); static const char* kSettingsGroup; - + PodcastEpisodeList EpisodesDownloading(const PodcastEpisodeList& episodes); QString DefaultDownloadDir() const; public slots: // Adds the episode to the download queue void DownloadEpisode(const PodcastEpisode& episode); + void cancelDownload(const PodcastEpisodeList& episodes); signals: void ProgressChanged(const PodcastEpisode& episode, diff --git a/src/podcasts/podcastepisode.cpp b/src/podcasts/podcastepisode.cpp index abfafba8a..db21cf3a9 100644 --- a/src/podcasts/podcastepisode.cpp +++ b/src/podcasts/podcastepisode.cpp @@ -17,17 +17,18 @@ along with Clementine. If not, see . */ -#include "podcast.h" #include "podcastepisode.h" -#include "core/logging.h" -#include "core/timeconstants.h" -#include "core/utilities.h" #include #include #include #include +#include "podcast.h" +#include "core/logging.h" +#include "core/timeconstants.h" +#include "core/utilities.h" + const QStringList PodcastEpisode::kColumns = QStringList() << "podcast_id" << "title" << "description" diff --git a/src/podcasts/podcastservice.cpp b/src/podcasts/podcastservice.cpp index 8e5e4fc95..352f58cf5 100644 --- a/src/podcasts/podcastservice.cpp +++ b/src/podcasts/podcastservice.cpp @@ -18,12 +18,17 @@ along with Clementine. If not, see . */ +#include "podcastservice.h" + +#include +#include +#include + #include "addpodcastdialog.h" #include "opmlcontainer.h" #include "podcastbackend.h" #include "podcastdeleter.h" #include "podcastdownloader.h" -#include "podcastservice.h" #include "podcastservicemodel.h" #include "podcastupdater.h" #include "core/application.h" @@ -39,10 +44,6 @@ #include "ui/organiseerrordialog.h" #include "ui/standarditemiconloader.h" -#include -#include -#include - const char* PodcastService::kServiceName = "Podcasts"; const char* PodcastService::kSettingsGroup = "Podcasts"; @@ -181,6 +182,32 @@ void PodcastService::CopyToDevice(const QModelIndexList& episode_indexes, if (organise_dialog_->SetSongs(songs)) organise_dialog_->show(); } +void PodcastService::CancelDownload() { + CancelDownload(selected_episodes_, explicitly_selected_podcasts_); +} + +void PodcastService::CancelDownload(const QModelIndexList& episode_indexes, + const QModelIndexList& podcast_indexes) { + PodcastEpisode episode_tmp; + SongList songs; + PodcastEpisodeList episodes; + Podcast podcast; + for (const QModelIndex& index : episode_indexes) { + episode_tmp = index.data(Role_Episode).value(); + episodes << episode_tmp; + } + + for (const QModelIndex& podcast : podcast_indexes) { + for (int i = 0; i < podcast.model()->rowCount(podcast); ++i) { + const QModelIndex& index = podcast.child(i, 0); + episode_tmp = index.data(Role_Episode).value(); + episodes << episode_tmp; + } + } + episodes = app_->podcast_downloader()->EpisodesDownloading(episodes); + app_->podcast_downloader()->cancelDownload(episodes); +} + void PodcastService::LazyPopulate(QStandardItem* parent) { switch (parent->data(InternetModel::Role_Type).toInt()) { case InternetModel::Type_Service: @@ -391,6 +418,9 @@ void PodcastService::ShowContextMenu(const QPoint& global_pos) { copy_to_device_ = context_menu_->addAction( IconLoader::Load("multimedia-player-ipod-mini-blue"), tr("Copy to device..."), this, SLOT(CopyToDevice())); + cancel_download_ = context_menu_->addAction( + IconLoader::Load("cancel"), + tr("Cancel download"), this, SLOT(CancelDownload())); remove_selected_action_ = context_menu_->addAction( IconLoader::Load("list-remove"), tr("Unsubscribe"), this, SLOT(RemoveSelectedPodcast())); @@ -452,6 +482,7 @@ void PodcastService::ShowContextMenu(const QPoint& global_pos) { remove_selected_action_->setEnabled(podcasts); set_new_action_->setEnabled(episodes || podcasts); set_listened_action_->setEnabled(episodes || podcasts); + cancel_download_->setEnabled(episodes || podcasts); if (selected_episodes_.count() == 1) { const PodcastEpisode episode = diff --git a/src/podcasts/podcastservice.h b/src/podcasts/podcastservice.h index 537c08aa4..4ca81be63 100644 --- a/src/podcasts/podcastservice.h +++ b/src/podcasts/podcastservice.h @@ -94,6 +94,9 @@ class PodcastService : public InternetService { void CopyToDevice(const PodcastEpisodeList& episodes_list); void CopyToDevice(const QModelIndexList& episode_indexes, const QModelIndexList& podcast_indexes); + void CancelDownload(); + void CancelDownload(const QModelIndexList& episode_indexes, + const QModelIndexList& podcast_indexes); private: void EnsureAddPodcastDialogCreated(); @@ -145,6 +148,7 @@ class PodcastService : public InternetService { QAction* set_new_action_; QAction* set_listened_action_; QAction* copy_to_device_; + QAction* cancel_download_; QStandardItem* root_; std::unique_ptr organise_dialog_;