File indexing completed on 2025-01-05 04:26:14

0001 /****************************************************************************************
0002  * Copyright (c) 2007 Bart Cerneels <bart.cerneels@kde.org>                             *
0003  *                                                                                      *
0004  * This program is free software; you can redistribute it and/or modify it under        *
0005  * the terms of the GNU General Public License as published by the Free Software        *
0006  * Foundation; either version 2 of the License, or (at your option) any later           *
0007  * version.                                                                             *
0008  *                                                                                      *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0011  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0012  *                                                                                      *
0013  * You should have received a copy of the GNU General Public License along with         *
0014  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0015  ****************************************************************************************/
0016 
0017 #ifndef SQLPODCASTPROVIDER_H
0018 #define SQLPODCASTPROVIDER_H
0019 
0020 #include "core/podcasts/PodcastProvider.h"
0021 #include "core/podcasts/PodcastReader.h"
0022 #include "SqlPodcastMeta.h"
0023 
0024 #include <QIcon>
0025 
0026 #include <KLocalizedString>
0027 
0028 class PodcastImageFetcher;
0029 
0030 class QDialog;
0031 class QUrl;
0032 class PodcastReader;
0033 class QTimer;
0034 
0035 namespace Ui {
0036     class SqlPodcastProviderSettingsWidget;
0037 }
0038 
0039 namespace Podcasts {
0040 
0041 /**
0042     @author Bart Cerneels <bart.cerneels@kde.org>
0043 */
0044 class AMAROK_EXPORT SqlPodcastProvider : public Podcasts::PodcastProvider
0045 {
0046     Q_OBJECT
0047     public:
0048         SqlPodcastProvider();
0049         ~SqlPodcastProvider() override;
0050 
0051         //TrackProvider methods
0052         bool possiblyContainsTrack( const QUrl &url ) const override;
0053         Meta::TrackPtr trackForUrl( const QUrl &url ) override;
0054 
0055         //PlaylistProvider methods
0056         QString prettyName() const override { return i18n("Local Podcasts"); }
0057         QIcon icon() const override { return QIcon::fromTheme( QStringLiteral("server-database") ); }
0058 
0059         Playlists::PlaylistList playlists() override;
0060 
0061         //PlaylistProvider methods
0062         QActionList providerActions() override;
0063         QActionList playlistActions( const Playlists::PlaylistList &playlists ) override;
0064         QActionList trackActions( const QMultiHash<Playlists::PlaylistPtr, int> &playlistTracks ) override;
0065 
0066         //PodcastProvider methods
0067         Podcasts::PodcastEpisodePtr episodeForGuid( const QString &guid ) override;
0068 
0069         void addPodcast( const QUrl &url ) override;
0070 
0071         Podcasts::PodcastChannelPtr addChannel( const Podcasts::PodcastChannelPtr &channel ) override;
0072         Podcasts::PodcastEpisodePtr addEpisode( Podcasts::PodcastEpisodePtr episode ) override;
0073 
0074         Podcasts::PodcastChannelList channels() override;
0075 
0076         void completePodcastDownloads() override;
0077 
0078         //SqlPodcastProvider specific methods
0079         virtual Podcasts::SqlPodcastChannelPtr podcastChannelForId( int podcastChannelDbId );
0080 
0081         virtual QUrl baseDownloadDir() const { return m_baseDownloadDir; }
0082 
0083     public Q_SLOTS:
0084         void updateAll() override;
0085         void downloadEpisode( const Podcasts::PodcastEpisodePtr &episode );
0086         void deleteDownloadedEpisode( const Podcasts::PodcastEpisodePtr &episode );
0087 
0088         void slotReadResult( PodcastReader *podcastReader );
0089         void downloadEpisode( Podcasts::SqlPodcastEpisodePtr episode );
0090         void deleteDownloadedEpisode( Podcasts::SqlPodcastEpisodePtr episode );
0091 
0092     private Q_SLOTS:
0093         void downloadResult( KJob * );
0094         void addData( KIO::Job *job, const QByteArray & data );
0095         void redirected( KIO::Job *, const QUrl& );
0096         void autoUpdate();
0097         void slotDeleteDownloadedEpisodes();
0098         void slotDownloadEpisodes();
0099         void slotSetKeep();
0100         void slotConfigureChannel();
0101         void slotRemoveChannels();
0102         void slotUpdateChannels();
0103         void slotDownloadProgress( KJob *job, unsigned long percent );
0104         void slotWriteTagsToFiles();
0105         void slotConfigChanged();
0106         void slotExportOpml();
0107 
0108     Q_SIGNALS:
0109         void totalPodcastDownloadProgress( int progress );
0110 
0111         //SqlPodcastProvider signals
0112         void episodeDownloaded( Podcasts::PodcastEpisodePtr );
0113         void episodeDeleted( Podcasts::PodcastEpisodePtr );
0114 
0115     private Q_SLOTS:
0116         void channelImageReady( Podcasts::PodcastChannelPtr, const QImage &);
0117         void podcastImageFetcherDone( PodcastImageFetcher * );
0118         void slotConfigureProvider();
0119 
0120         void slotStatusBarNewProgressOperation( KIO::TransferJob * job,
0121                                                                const QString &description,
0122                                                                Podcasts::PodcastReader* reader );
0123         void slotStatusBarErrorMessage( const QString &message );
0124         void slotOpmlWriterDone( int result );
0125 
0126     private:
0127         void startTimer();
0128         void configureProvider();
0129         void configureChannel( Podcasts::SqlPodcastChannelPtr channel );
0130         void updateSqlChannel( Podcasts::SqlPodcastChannelPtr channel );
0131 
0132         /** creates all the necessary tables, indexes etc. for the database */
0133         void createTables() const;
0134         void loadPodcasts();
0135 
0136         /** @arg string: a url, localUrl or guid in string form */
0137         Podcasts::SqlPodcastEpisodePtr sqlEpisodeForString( const QString &string );
0138 
0139         void updateDatabase( int fromVersion, int toVersion );
0140         void fetchImage( const Podcasts::SqlPodcastChannelPtr &channel );
0141 
0142         /** shows a modal dialog asking the user if he really wants to unsubscribe
0143             and if he wants to keep the podcast media */
0144         QPair<bool, bool> confirmUnsubscribe( Podcasts::SqlPodcastChannelPtr channel );
0145 
0146         /** remove the episodes in the list from the filesystem */
0147         void deleteDownloadedEpisodes( Podcasts::SqlPodcastEpisodeList &episodes );
0148 
0149         void moveDownloadedEpisodes( Podcasts::SqlPodcastChannelPtr channel );
0150 
0151         /** Removes a podcast from the list. Will ask for confirmation to delete the episodes
0152           * as well
0153           */
0154         void removeSubscription( Podcasts::SqlPodcastChannelPtr channel );
0155 
0156         void subscribe( const QUrl &url );
0157         QFile* createTmpFile ( Podcasts::SqlPodcastEpisodePtr sqlEpisode );
0158         void cleanupDownload( KJob *job, bool downloadFailed );
0159 
0160         /** returns true if the file that is downloaded by 'job' is already locally available */
0161         bool checkEnclosureLocallyAvailable( KIO::Job *job );
0162 
0163         Podcasts::SqlPodcastChannelList m_channels;
0164 
0165         QTimer *m_updateTimer;
0166         int m_autoUpdateInterval; //interval between autoupdate attempts in minutes
0167         unsigned int m_updatingChannels;
0168         unsigned int m_maxConcurrentUpdates;
0169         Podcasts::SqlPodcastChannelList m_updateQueue;
0170         QList<QUrl> m_subscribeQueue;
0171 
0172         struct PodcastEpisodeDownload {
0173             Podcasts::SqlPodcastEpisodePtr episode;
0174             QFile *tmpFile;
0175             QString fileName;
0176             bool finalNameReady;
0177         };
0178 
0179         QHash<KJob *, struct PodcastEpisodeDownload> m_downloadJobMap;
0180 
0181         Podcasts::SqlPodcastEpisodeList m_downloadQueue;
0182         int m_maxConcurrentDownloads;
0183         int m_completedDownloads;
0184 
0185         QUrl m_baseDownloadDir;
0186 
0187         QDialog *m_providerSettingsDialog;
0188         Ui::SqlPodcastProviderSettingsWidget *m_providerSettingsWidget;
0189 
0190         QList<QAction *> m_providerActions;
0191 
0192         QAction *m_configureChannelAction; //Configure a Channel
0193         QAction *m_deleteAction; //delete a downloaded Episode
0194         QAction *m_downloadAction;
0195         QAction *m_keepAction;
0196         QAction *m_removeAction; //remove a subscription
0197         QAction *m_updateAction;
0198         QAction *m_writeTagsAction; //write feed information to downloaded file
0199 
0200         PodcastImageFetcher *m_podcastImageFetcher;
0201 };
0202 
0203 } //namespace Podcasts
0204 
0205 #endif