File indexing completed on 2024-05-19 04:50:24

0001 /****************************************************************************************
0002  * Copyright (c) 2008 Nikolaj Hald Nielsen <nhn@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 #include "OpmlDirectoryService.h"
0018 
0019 #include "amarokurls/AmarokUrlHandler.h"
0020 #include "core/support/Debug.h"
0021 #include "core/support/Components.h"
0022 #include "core/logger/Logger.h"
0023 #include "browsers/CollectionTreeItem.h"
0024 #include "browsers/SingleCollectionTreeItemModel.h"
0025 #include "OpmlDirectoryInfoParser.h"
0026 #include "OpmlDirectoryModel.h"
0027 #include "OpmlDirectoryView.h"
0028 #include "playlistmanager/PlaylistManager.h"
0029 #include "core/podcasts/PodcastProvider.h"
0030 #include "ServiceSqlRegistry.h"
0031 #include "widgets/SearchWidget.h"
0032 
0033 #include <QStandardPaths>
0034 
0035 #include <KIconThemes/KIconLoader>
0036 
0037 
0038 using namespace Meta;
0039 
0040 
0041 OpmlDirectoryServiceFactory::OpmlDirectoryServiceFactory()
0042     : ServiceFactory()
0043 {}
0044 
0045 OpmlDirectoryServiceFactory::~OpmlDirectoryServiceFactory()
0046 {}
0047 
0048 void OpmlDirectoryServiceFactory::init()
0049 {
0050     ServiceBase* service = new OpmlDirectoryService( this, "OpmlDirectory", i18n( "Podcast Directory" ) );
0051     m_initialized = true;
0052     Q_EMIT newService( service );
0053 }
0054 
0055 
0056 QString OpmlDirectoryServiceFactory::name()
0057 {
0058     return "OpmlDirectory";
0059 }
0060 
0061 KConfigGroup OpmlDirectoryServiceFactory::config()
0062 {
0063     return Amarok::config( "Service_OpmlDirectory" );
0064 }
0065 
0066 
0067 OpmlDirectoryService::OpmlDirectoryService( OpmlDirectoryServiceFactory* parent, const QString &name, const QString &prettyName )
0068  : ServiceBase( name, parent, false, prettyName )
0069 {
0070     setShortDescription( i18n( "A large listing of podcasts" ) );
0071     setIcon( QIcon::fromTheme( "view-services-opml-amarok" ) );
0072 
0073     setLongDescription( i18n( "A comprehensive list of searchable podcasts that you can subscribe to directly from within Amarok." ) );
0074 
0075     KIconLoader loader;
0076     setImagePath( loader.iconPath( "view-services-opml-amarok", -128, true ) );
0077 
0078     The::amarokUrlHandler()->registerRunner( this, command() );
0079 
0080     setServiceReady( true );
0081 }
0082 
0083 
0084 OpmlDirectoryService::~OpmlDirectoryService()
0085 {
0086 }
0087 
0088 void OpmlDirectoryService::polish()
0089 {
0090     generateWidgetInfo();
0091     if ( m_polished )
0092         return;
0093 
0094     //do not allow this content to get added to the playlist. At least not for now
0095     setPlayableTracks( false );
0096 
0097     //TODO: implement searching
0098     m_searchWidget->setVisible( false );
0099 
0100     OpmlDirectoryView* opmlView = new OpmlDirectoryView( this );
0101     opmlView->setHeaderHidden( true );
0102     opmlView->setFrameShape( QFrame::NoFrame );
0103     opmlView->setDragEnabled ( true );
0104     opmlView->setSortingEnabled( false );
0105     opmlView->setSelectionMode( QAbstractItemView::ExtendedSelection );
0106     opmlView->setDragDropMode ( QAbstractItemView::DragOnly );
0107     opmlView->setEditTriggers( QAbstractItemView::SelectedClicked | QAbstractItemView::EditKeyPressed );
0108     setView( opmlView );
0109     QString opmlLocation = Amarok::saveLocation() + "podcast_directory.opml";
0110 
0111     if( !QFile::exists( opmlLocation ) )
0112     {
0113         //copy from the standard data dir
0114         QString schippedOpmlLocation = QStandardPaths::locate( QStandardPaths::GenericDataLocation, "amarok/data/podcast_directory.opml" );
0115         if( !QFile::copy( schippedOpmlLocation, opmlLocation ) )
0116         {
0117             debug() << QString( "Failed to copy from %1 to %2" )
0118             .arg( schippedOpmlLocation, opmlLocation );
0119             //TODO: error box drawn in the view's area.
0120             return;
0121         }
0122     }
0123 
0124     setModel( new OpmlDirectoryModel( QUrl::fromLocalFile( opmlLocation ), this ) );
0125 
0126     m_subscribeButton = new QPushButton( m_bottomPanel );
0127     m_subscribeButton->setText( i18n( "Subscribe" ) );
0128     m_subscribeButton->setObjectName( "subscribeButton" );
0129     m_subscribeButton->setIcon( QIcon::fromTheme( QStringLiteral("get-hot-new-stuff-amarok") ) );
0130 
0131     m_subscribeButton->setEnabled( false );
0132 
0133     connect( m_subscribeButton, &QPushButton::clicked, this, &OpmlDirectoryService::subscribe );
0134 
0135     m_addOpmlButton = new QPushButton( m_bottomPanel );
0136     m_addOpmlButton->setText( i18n( "Add OPML" ) );
0137     m_addOpmlButton->setObjectName( QStringLiteral("addOpmlButton") );
0138     m_addOpmlButton->setIcon( QIcon::fromTheme( QStringLiteral("list-add-amarok") ) );
0139 
0140     connect( m_addOpmlButton, &QPushButton::clicked,
0141              dynamic_cast<OpmlDirectoryModel*>( model() ), &OpmlDirectoryModel::slotAddOpmlAction );
0142 
0143     connect( view()->selectionModel(), &QItemSelectionModel::selectionChanged,
0144              this, &OpmlDirectoryService::slotSelectionChanged );
0145 
0146     setInfoParser( new OpmlDirectoryInfoParser() );
0147 
0148     m_polished = true;
0149 }
0150 
0151 QString
0152 OpmlDirectoryService::command() const
0153 {
0154     return "service-podcastdirectory";
0155 }
0156 
0157 QString
0158 OpmlDirectoryService::prettyCommand() const
0159 {
0160     return i18n( "Add an OPML file to the list." );
0161 }
0162 
0163 bool
0164 OpmlDirectoryService::run(const AmarokUrl &url )
0165 {
0166     //make sure this category is shown.
0167     AmarokUrl( "amarok://navigate/internet/OpmlDirectory" ).run();
0168     if( url.path() == QLatin1String( "addOpml" ) )
0169     {
0170         OpmlDirectoryModel *opmlModel = qobject_cast<OpmlDirectoryModel *>( model() );
0171         Q_ASSERT_X(opmlModel, "OpmlDirectoryService::run()", "fix if a proxy is used");
0172 
0173         opmlModel->slotAddOpmlAction();
0174         return true;
0175     }
0176 
0177     return false;
0178 }
0179 
0180 void
0181 OpmlDirectoryService::subscribe()
0182 {
0183     OpmlDirectoryModel * opmlModel = dynamic_cast<OpmlDirectoryModel *>( model() );
0184     Q_ASSERT( opmlModel );
0185     opmlModel->subscribe( view()->selectionModel()->selectedIndexes() );
0186 }
0187 
0188 void
0189 OpmlDirectoryService::slotSelectionChanged( const QItemSelection &selected,
0190                                             const QItemSelection &deselected )
0191 {
0192     Q_UNUSED(selected)
0193     Q_UNUSED(deselected)
0194     m_subscribeButton->setEnabled( !view()->selectionModel()->selectedIndexes().isEmpty() );
0195 }