File indexing completed on 2024-05-19 04:48:41
0001 /**************************************************************************************** 0002 * Copyright (c) 2007-2010 Bart Cerneels <bart.cerneels@kde.org> * 0003 * Copyright (c) 2007-2008 Nikolaj Hald Nielsen <nhn@kde.org> * 0004 * Copyright (c) 2007 Henry de Valence <hdevalence@gmail.com> * 0005 * * 0006 * This program is free software; you can redistribute it and/or modify it under * 0007 * the terms of the GNU General Public License as published by the Free Software * 0008 * Foundation; either version 2 of the License, or (at your option) any later * 0009 * version. * 0010 * * 0011 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0012 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0013 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License along with * 0016 * this program. If not, see <http://www.gnu.org/licenses/>. * 0017 ****************************************************************************************/ 0018 0019 #define DEBUG_PREFIX "PodcastCategory" 0020 0021 #include "PodcastCategory.h" 0022 0023 #include "amarokconfig.h" 0024 #include "amarokurls/AmarokUrl.h" 0025 #include "App.h" 0026 #include "browsers/InfoProxy.h" 0027 #include "core/support/Debug.h" 0028 #include "core/meta/support/MetaUtility.h" 0029 #include "PaletteHandler.h" 0030 #include "PodcastModel.h" 0031 #include "PlaylistBrowserView.h" 0032 #include "widgets/PrettyTreeRoles.h" 0033 0034 #include <QModelIndexList> 0035 #include <QTextBrowser> 0036 0037 #include <QAction> 0038 #include <QIcon> 0039 #include <QStandardPaths> 0040 #include <KUrlRequesterDialog> 0041 0042 #include <KLocalizedString> 0043 #include <KToolBar> 0044 0045 namespace The 0046 { 0047 PlaylistBrowserNS::PodcastCategory* podcastCategory() 0048 { 0049 return PlaylistBrowserNS::PodcastCategory::instance(); 0050 } 0051 } 0052 0053 using namespace PlaylistBrowserNS; 0054 0055 QString PodcastCategory::s_configGroup( QStringLiteral("Podcast View") ); 0056 0057 PodcastCategory* PodcastCategory::s_instance = nullptr; 0058 0059 PodcastCategory* 0060 PodcastCategory::instance() 0061 { 0062 return s_instance ? s_instance : new PodcastCategory( nullptr ); 0063 } 0064 0065 void 0066 PodcastCategory::destroy() 0067 { 0068 if( s_instance ) 0069 { 0070 delete s_instance; 0071 s_instance = nullptr; 0072 } 0073 } 0074 0075 PodcastCategory::PodcastCategory( QWidget *parent ) 0076 : PlaylistBrowserCategory( Playlists::PodcastChannelPlaylist, 0077 QStringLiteral("podcasts"), 0078 s_configGroup, 0079 The::podcastModel(), 0080 parent ) 0081 { 0082 setPrettyName( i18n( "Podcasts" ) ); 0083 setShortDescription( i18n( "List of podcast subscriptions and episodes" ) ); 0084 setIcon( QIcon::fromTheme( QStringLiteral("podcast-amarok") ) ); 0085 0086 setLongDescription( i18n( "Manage your podcast subscriptions and browse individual episodes. " 0087 "Downloading episodes to the disk is also done here, or you can tell " 0088 "Amarok to do this automatically." ) ); 0089 0090 setImagePath( QStandardPaths::locate( QStandardPaths::GenericDataLocation, QStringLiteral("amarok/images/hover_info_podcasts.png") ) ); 0091 0092 // set background 0093 if( AmarokConfig::showBrowserBackgroundImage() ) 0094 setBackgroundImage( imagePath() ); 0095 0096 QAction *addPodcastAction = new QAction( QIcon::fromTheme( QStringLiteral("list-add-amarok") ), i18n("&Add Podcast"), 0097 m_toolBar ); 0098 addPodcastAction->setPriority( QAction::NormalPriority ); 0099 m_toolBar->insertAction( m_separator, addPodcastAction ); 0100 connect( addPodcastAction, &QAction::triggered, The::podcastModel(), &PodcastModel::addPodcast ); 0101 0102 QAction *updateAllAction = new QAction( QIcon::fromTheme(QStringLiteral("view-refresh-amarok")), QString(), m_toolBar ); 0103 updateAllAction->setToolTip( i18n("&Update All") ); 0104 updateAllAction->setPriority( QAction::LowPriority ); 0105 m_toolBar->insertAction( m_separator, updateAllAction ); 0106 connect( updateAllAction, &QAction::triggered, 0107 The::podcastModel(), &PodcastModel::refreshPodcasts ); 0108 0109 0110 QAction *importOpmlAction = new QAction( QIcon::fromTheme(QStringLiteral("document-import")) 0111 , i18n( "Import OPML File" ) 0112 , m_toolBar 0113 ); 0114 importOpmlAction->setToolTip( i18n( "Import OPML File" ) ); 0115 importOpmlAction->setPriority( QAction::LowPriority ); 0116 m_toolBar->addAction( importOpmlAction ); 0117 connect( importOpmlAction, &QAction::triggered, this, &PodcastCategory::slotImportOpml ); 0118 0119 PlaylistBrowserView *view = static_cast<PlaylistBrowserView*>( playlistView() ); 0120 connect( view, &PlaylistBrowserView::currentItemChanged, this, &PodcastCategory::showInfo ); 0121 0122 //transparency 0123 // QPalette p = m_podcastTreeView->palette(); 0124 // QColor c = p.color( QPalette::Base ); 0125 // c.setAlpha( 0 ); 0126 // p.setColor( QPalette::Base, c ); 0127 // 0128 // c = p.color( QPalette::AlternateBase ); 0129 // c.setAlpha( 77 ); 0130 // p.setColor( QPalette::AlternateBase, c ); 0131 // 0132 // m_podcastTreeView->setPalette( p ); 0133 // 0134 // QSizePolicy sizePolicy1(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding); 0135 // sizePolicy1.setHorizontalStretch(0); 0136 // sizePolicy1.setVerticalStretch(0); 0137 // sizePolicy1.setHeightForWidth(m_podcastTreeView->sizePolicy().hasHeightForWidth()); 0138 // m_podcastTreeView->setSizePolicy(sizePolicy1); 0139 } 0140 0141 PodcastCategory::~PodcastCategory() 0142 { 0143 } 0144 0145 void 0146 PodcastCategory::showInfo( const QModelIndex &index ) 0147 { 0148 if( !index.isValid() ) 0149 return; 0150 0151 const int row = index.row(); 0152 QString description; 0153 QString title( index.data( Qt::DisplayRole ).toString() ); 0154 QString subtitle( index.sibling( row, SubtitleColumn ).data( Qt::DisplayRole ).toString() ); 0155 QUrl imageUrl( qvariant_cast<QUrl>( 0156 index.sibling( row, ImageColumn ).data( Qt::DisplayRole ) 0157 ) ); 0158 QString author( index.sibling( row, AuthorColumn ).data( Qt::DisplayRole ).toString() ); 0159 QStringList keywords( qvariant_cast<QStringList>( 0160 index.sibling( row, KeywordsColumn ).data( Qt::DisplayRole ) 0161 ) ); 0162 bool isEpisode = index.sibling( row, IsEpisodeColumn ).data( Qt::DisplayRole ).toBool(); 0163 QString authorAndPubDate; 0164 0165 if( !author.isEmpty() ) 0166 { 0167 authorAndPubDate = QStringLiteral( "<b>%1</b> %2 " ) 0168 .arg( i18n( "By" ), 0169 author.toHtmlEscaped() ); 0170 } 0171 0172 if( !subtitle.isEmpty() ) 0173 { 0174 description += QStringLiteral( "<h1 class=\"subtitle\">%1</h1>" ) 0175 .arg( subtitle.toHtmlEscaped() ); 0176 } 0177 0178 if( !imageUrl.isEmpty() ) 0179 { 0180 description += QString( "<p style=\"float:right;\"><img src=\"%1\" onclick=\"" 0181 "if (this.style.width=='150px') {" 0182 "this.style.width='auto';" 0183 "this.style.marginLeft='0em';" 0184 "this.style.cursor='-webkit-zoom-out';" 0185 "this.parentNode.style.float='inherit';" 0186 "this.parentNode.style.textAlign='center';" 0187 "} else {" 0188 "this.style.width='150px';" 0189 "this.style.marginLeft='1em';" 0190 "this.style.cursor='-webkit-zoom-in';" 0191 "this.parentNode.style.float='right';" 0192 "this.parentNode.style.textAlign='inherit';" 0193 "}\"" 0194 " style=\"width: 150px; margin-left: 1em;" 0195 " margin-right: 0em; cursor: -webkit-zoom-in;\"" 0196 "/></p>" ) 0197 .arg( imageUrl.url().toHtmlEscaped() ); 0198 } 0199 0200 if( isEpisode ) 0201 { 0202 QDateTime pubDate( index.sibling( row, DateColumn ).data( Qt::DisplayRole ).toDateTime() ); 0203 0204 if( pubDate.isValid() ) 0205 { 0206 authorAndPubDate += QStringLiteral( "<b>%1</b> %2" ) 0207 .arg( i18nc( "Podcast published on date", "On" ), 0208 QLocale().toString( pubDate, QLocale::ShortFormat ) ); 0209 } 0210 } 0211 0212 if( !authorAndPubDate.isEmpty() ) 0213 { 0214 description += QStringLiteral( "<p>%1</p>" ) 0215 .arg( authorAndPubDate ); 0216 } 0217 0218 if( isEpisode ) 0219 { 0220 int fileSize = index.sibling( row, FilesizeColumn ).data( Qt::DisplayRole ).toInt(); 0221 0222 if( fileSize != 0 ) 0223 { 0224 description += QStringLiteral( "<p><b>%1</b> %2</p>" ) 0225 .arg( i18n( "File Size:" ), 0226 Meta::prettyFilesize( fileSize ) ); 0227 } 0228 0229 } 0230 else 0231 { 0232 QDate subsDate( index.sibling( row, DateColumn ).data( Qt::DisplayRole ).toDate() ); 0233 0234 if( subsDate.isValid() ) 0235 { 0236 description += QStringLiteral( "<p><b>%1</b> %2</p>" ) 0237 .arg( i18n( "Subscription Date:" ), 0238 QLocale().toString( subsDate, QLocale::ShortFormat ) ); 0239 } 0240 } 0241 0242 if( !keywords.isEmpty() ) 0243 { 0244 description += QStringLiteral( "<p><b>%1</b> %2</p>" ) 0245 .arg( i18n( "Keywords:" ), 0246 keywords.join( QStringLiteral(", ") ).toHtmlEscaped() ); 0247 } 0248 0249 description += index.data( PrettyTreeRoles::ByLineRole ).toString(); 0250 0251 description = QString( 0252 "<html>" 0253 " <head>" 0254 " <title>%1</title>" 0255 " <style type=\"text/css\">" 0256 "body {color: %3;}" 0257 "::selection {background-color: %4;}" 0258 "h1 {text-align:center; font-size: 1.2em;}" 0259 "h1.subtitle {text-align:center; font-size: 1em; font-weight: normal;}" 0260 " </style>" 0261 " </head>" 0262 " <body>" 0263 " <h1>%1</h1>" 0264 " %2" 0265 " </body>" 0266 "</html>") 0267 .arg( title.toHtmlEscaped(), 0268 description, 0269 pApp->palette().brush( QPalette::Text ).color().name(), 0270 The::paletteHandler()->highlightColor().name() ); 0271 0272 QVariantMap map; 0273 map[QStringLiteral("service_name")] = title; 0274 map[QStringLiteral("main_info")] = description; 0275 The::infoProxy()->setInfo( map ); 0276 } 0277 0278 void 0279 PodcastCategory::slotImportOpml() 0280 { 0281 AmarokUrl( QStringLiteral("amarok://service-podcastdirectory/addOpml") ).run(); 0282 } 0283