File indexing completed on 2024-05-19 04:50:24
0001 /**************************************************************************************** 0002 * Copyright (c) 2007 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 "ScriptableService.h" 0018 0019 #include "scripting/scriptmanager/ScriptManager.h" 0020 #include "browsers/CollectionTreeItem.h" 0021 #include "browsers/SingleCollectionTreeItemModel.h" 0022 #include "browsers/servicebrowser/ServiceBrowser.h" 0023 #include "core/support/Amarok.h" 0024 #include "core/support/Debug.h" 0025 #include "services/scriptable/ScriptableServiceCollectionTreeModel.h" 0026 #include "services/scriptable/ScriptableServiceInfoParser.h" 0027 #include "widgets/SearchWidget.h" 0028 0029 #include <QStandardPaths> 0030 0031 using namespace Meta; 0032 0033 ScriptableService::ScriptableService( const QString & name ) 0034 : ServiceBase( name, nullptr ) 0035 , m_polished( false ) 0036 , m_name( name ) 0037 , m_trackIdCounter( 0 ) 0038 , m_albumIdCounter( 0 ) 0039 , m_artistIdCounter( 0 ) 0040 , m_genreIdCounter( 0 ) 0041 { 0042 DEBUG_BLOCK 0043 debug() << "creating ScriptableService " << name; 0044 m_collection = nullptr; 0045 m_bottomPanel->hide(); 0046 } 0047 0048 ScriptableService::~ScriptableService() 0049 { 0050 m_collection->deleteLater(); 0051 } 0052 0053 void ScriptableService::init( int levels, const QString & rootHtml, bool showSearchBar ) 0054 { 0055 DEBUG_BLOCK 0056 m_levels = levels; 0057 m_rootHtml = rootHtml; 0058 m_hasSearchBar = showSearchBar; 0059 m_searchWidget->showAdvancedButton( false ); 0060 setInfoParser( new ScriptableServiceInfoParser( m_name ) ); 0061 m_collection = new Collections::ScriptableServiceCollection( m_name ); 0062 m_collection->setLevels( levels ); 0063 0064 if ( !showSearchBar ) 0065 m_searchWidget->hide(); 0066 } 0067 0068 Collections::ServiceCollection * ScriptableService::collection() 0069 { 0070 return m_collection; 0071 } 0072 0073 0074 int ScriptableService::insertItem( int level, int parentId, const QString & name, const QString & infoHtml, const QString & callbackData, const QString & playableUrl, 0075 const QString & albumOverride, const QString & artistOverride, const QString & genreOverride, 0076 const QString & composerOverride, int yearOverride, const QString &coverUrl ) 0077 { 0078 0079 /* 0080 please don't remove this block as I regularly need it for debugging - nhn 0081 DEBUG_BLOCK 0082 debug() << "level: " << level; 0083 debug() << "parentId: " << parentId; 0084 debug() << "name: " << name; 0085 debug() << "infoHtml: " << infoHtml; 0086 debug() << "callbackData: " << callbackData; 0087 debug() << "playableUrl: " << playableUrl; 0088 0089 debug() << "albumOverride: " << albumOverride; 0090 debug() << "artistOverride: " << artistOverride; 0091 debug() << "coverUrl: " << coverUrl;*/ 0092 0093 if ( ( level +1 > m_levels ) || level < 0 ) 0094 return -1; 0095 0096 switch ( level ) { 0097 0098 case 0: 0099 { 0100 if( !callbackData.isEmpty() || playableUrl.isEmpty() ) 0101 return -1; 0102 0103 AmarokSharedPointer<ScriptableServiceTrack> track( new ScriptableServiceTrack( name ) ); 0104 track->setAlbumId( parentId ); 0105 track->setUidUrl( playableUrl ); 0106 track->setServiceName( m_name ); 0107 track->setDescription( infoHtml ); 0108 0109 if ( !m_customEmblem.isNull() ) 0110 track->setServiceEmblem( m_customEmblem ); 0111 else 0112 track->setServiceEmblem( QPixmap( QStandardPaths::locate( QStandardPaths::GenericDataLocation, QStringLiteral("amarok/images/emblem-scripted.png") ) ) ); 0113 0114 if ( !m_customScalableEmblem.isEmpty() ) 0115 track->setServiceScalableEmblem( m_customScalableEmblem ); 0116 else 0117 track->setServiceEmblem( QStandardPaths::locate( QStandardPaths::GenericDataLocation, QStringLiteral("amarok/images/emblem-scripted-scalable.svgz") ) ); 0118 0119 if ( !albumOverride.isEmpty() ) 0120 track->setAlbumName( albumOverride ); 0121 if ( !artistOverride.isEmpty() ) 0122 track->setArtistName( artistOverride ); 0123 if ( !genreOverride.isEmpty() ) 0124 track->setGenreName( genreOverride ); 0125 if ( !composerOverride.isEmpty() ) 0126 track->setComposerName( composerOverride ); 0127 if ( yearOverride != 0 ) 0128 track->setYearNumber( yearOverride ); 0129 if ( !coverUrl.isEmpty() ) 0130 track->setCustomAlbumCoverUrl( coverUrl ); 0131 0132 return addTrack( track.data() ); 0133 break; 0134 0135 } case 1: 0136 { 0137 if ( callbackData.isEmpty() || !playableUrl.isEmpty() ) 0138 return -1; 0139 0140 ScriptableServiceAlbum * album = new ScriptableServiceAlbum( name ); 0141 album->setCallbackString( callbackData ); 0142 album->setArtistId( parentId ); 0143 album->setDescription( infoHtml ); 0144 album->setServiceName( m_name ); 0145 //debug() << "setting coverUrl: " << coverUrl; 0146 album->setCoverUrl( coverUrl ); 0147 0148 album->setServiceName( m_name ); 0149 album->setDescription( infoHtml ); 0150 0151 if ( !m_customEmblem.isNull() ) 0152 album->setServiceEmblem( m_customEmblem ); 0153 else 0154 album->setServiceEmblem( QPixmap( QStandardPaths::locate( QStandardPaths::GenericDataLocation, QStringLiteral("amarok/images/emblem-scripted.png") ) ) ); 0155 0156 if ( !m_customScalableEmblem.isEmpty() ) 0157 album->setServiceScalableEmblem( m_customScalableEmblem ); 0158 else 0159 album->setServiceEmblem( QStandardPaths::locate( QStandardPaths::GenericDataLocation, QStringLiteral("amarok/images/emblem-scripted-scalable.svgz") ) ); 0160 0161 return addAlbum( album ); 0162 0163 } case 2: 0164 { 0165 if ( callbackData.isEmpty() || !playableUrl.isEmpty() ) 0166 return -1; 0167 0168 ScriptableServiceArtist * artist = new ScriptableServiceArtist( name ); 0169 artist->setCallbackString( callbackData ); 0170 artist->setGenreId( parentId ); 0171 artist->setDescription( infoHtml ); 0172 artist->setServiceName( m_name ); 0173 0174 artist->setServiceName( m_name ); 0175 artist->setDescription( infoHtml ); 0176 0177 if ( !m_customEmblem.isNull() ) 0178 artist->setServiceEmblem( m_customEmblem ); 0179 else 0180 artist->setServiceEmblem( QPixmap( QStandardPaths::locate( QStandardPaths::GenericDataLocation, QStringLiteral("amarok/images/emblem-scripted.png") ) ) ); 0181 0182 if ( !m_customScalableEmblem.isEmpty() ) 0183 artist->setServiceScalableEmblem( m_customScalableEmblem ); 0184 else 0185 artist->setServiceEmblem( QStandardPaths::locate( QStandardPaths::GenericDataLocation, QStringLiteral("amarok/images/emblem-scripted-scalable.svgz") ) ); 0186 0187 0188 return addArtist( artist ); 0189 0190 } case 3: 0191 { 0192 0193 if ( callbackData.isEmpty() || !playableUrl.isEmpty() || parentId != -1 ) 0194 return -1; 0195 0196 ScriptableServiceGenre * genre = new ScriptableServiceGenre( name ); 0197 genre->setCallbackString( callbackData ); 0198 genre->setDescription( infoHtml ); 0199 genre->setServiceName( m_name ); 0200 0201 genre->setServiceName( m_name ); 0202 genre->setDescription( infoHtml ); 0203 0204 if ( !m_customEmblem.isNull() ) 0205 genre->setServiceEmblem( m_customEmblem ); 0206 else 0207 genre->setServiceEmblem( QPixmap( QStandardPaths::locate( QStandardPaths::GenericDataLocation, QStringLiteral("amarok/images/emblem-scripted.png") ) ) ); 0208 0209 if ( !m_customScalableEmblem.isEmpty() ) 0210 genre->setServiceScalableEmblem( m_customScalableEmblem ); 0211 else 0212 genre->setServiceEmblem( QStandardPaths::locate( QStandardPaths::GenericDataLocation, QStringLiteral("amarok/images/emblem-scripted-scalable.svgz") ) ); 0213 0214 0215 return addGenre( genre ); 0216 0217 } 0218 } 0219 return -1; 0220 } 0221 0222 0223 int ScriptableService::addTrack( ScriptableServiceTrack * track ) 0224 { 0225 int artistId = -1; 0226 int genreId = -1; 0227 0228 TrackPtr trackPtr = TrackPtr( track ); 0229 m_collection->acquireWriteLock(); 0230 m_collection->addTrack( trackPtr ); 0231 m_collection->releaseLock(); 0232 0233 m_trackIdCounter++; 0234 track->setId( m_trackIdCounter ); 0235 0236 0237 int albumId = track->albumId(); 0238 0239 //handle albums 0240 if ( m_levels > 1 ) { 0241 0242 if ( !m_ssAlbumIdMap.contains( albumId ) ){ 0243 return -1; 0244 } 0245 0246 ScriptableServiceAlbum * album = m_ssAlbumIdMap.value( albumId ); 0247 0248 track->setAlbum( album->prettyName() ); 0249 track->setAlbumPtr( AlbumPtr( album ) ); 0250 album->addTrack( trackPtr ); 0251 0252 artistId = album->artistId(); 0253 0254 } 0255 0256 if ( m_levels > 2 ) { 0257 0258 if ( !m_ssArtistIdMap.contains( artistId ) ) { 0259 return -1; 0260 } 0261 0262 ScriptableServiceArtist * artist = m_ssArtistIdMap.value( artistId ); 0263 track->setArtist( artist->prettyName() ); 0264 track->setArtist( ArtistPtr( artist ) ); 0265 artist->addTrack( trackPtr ); 0266 0267 genreId = artist->genreId(); 0268 } 0269 0270 if ( m_levels == 4) { 0271 0272 if ( !m_ssGenreIdMap.contains( genreId ) ) { 0273 return -1; 0274 } 0275 0276 ScriptableServiceGenre * genre = m_ssGenreIdMap.value( genreId ); 0277 track->setGenre( genre->prettyName() ); 0278 track->setGenre( GenrePtr( genre ) ); 0279 genre->addTrack( trackPtr ); 0280 0281 } 0282 0283 m_ssTrackIdMap.insert( m_trackIdCounter, track ); 0284 m_collection->acquireWriteLock(); 0285 m_collection->addTrack( trackPtr ); 0286 m_collection->releaseLock(); 0287 0288 //m_collection->emitUpdated(); 0289 0290 return m_trackIdCounter; 0291 } 0292 0293 int ScriptableService::addAlbum( ScriptableServiceAlbum * album ) 0294 { 0295 int artistId = album->artistId(); 0296 if ( m_levels > 2 && !m_ssArtistIdMap.contains( artistId ) ) { 0297 delete album; 0298 return -1; 0299 } 0300 0301 album->setAlbumArtist( ArtistPtr( m_ssArtistIdMap.value( artistId ) ) ); 0302 0303 AlbumPtr albumPtr = AlbumPtr( album ); 0304 m_albumIdCounter++; 0305 album->setId( m_albumIdCounter ); 0306 m_ssAlbumIdMap.insert( m_albumIdCounter, album ); 0307 m_collection->acquireWriteLock(); 0308 m_collection->addAlbum( albumPtr ); 0309 m_collection->releaseLock(); 0310 //m_collection->emitUpdated(); 0311 return m_albumIdCounter; 0312 } 0313 0314 int ScriptableService::addArtist( Meta::ScriptableServiceArtist * artist ) 0315 { 0316 int genreId = artist->genreId(); 0317 if ( m_levels > 3 && !m_ssGenreIdMap.contains( genreId ) ) { 0318 delete artist; 0319 return -1; 0320 } 0321 0322 ArtistPtr artistPtr = ArtistPtr( artist ); 0323 m_artistIdCounter++; 0324 artist->setId( m_artistIdCounter ); 0325 m_ssArtistIdMap.insert( m_artistIdCounter, artist ); 0326 m_collection->acquireWriteLock(); 0327 m_collection->addArtist( artistPtr ); 0328 m_collection->releaseLock(); 0329 0330 return m_artistIdCounter; 0331 0332 } 0333 0334 int ScriptableService::addGenre( Meta::ScriptableServiceGenre * genre ) 0335 { 0336 GenrePtr genrePtr = GenrePtr( genre ); 0337 m_genreIdCounter++; 0338 0339 //debug() << "adding genre: " << genre->name() << ", with id: " << m_genreIdCounter; 0340 0341 genre->setId( m_genreIdCounter ); 0342 m_ssGenreIdMap.insert( m_genreIdCounter, genre ); 0343 m_collection->acquireWriteLock(); 0344 m_collection->addGenre( genrePtr ); 0345 m_collection->releaseLock(); 0346 0347 return m_genreIdCounter; 0348 } 0349 0350 void ScriptableService::donePopulating( int parentId ) 0351 { 0352 m_collection->donePopulating( parentId ); 0353 } 0354 0355 void ScriptableService::polish() 0356 { 0357 0358 if ( !m_polished ) { 0359 QList<CategoryId::CatMenuId> viewLevels; 0360 0361 switch ( m_levels ) { 0362 case 1: 0363 break; 0364 case 2: 0365 viewLevels << CategoryId::Album; 0366 break; 0367 case 3: 0368 viewLevels << CategoryId::Artist << CategoryId::Album; 0369 break; 0370 case 4: 0371 viewLevels << CategoryId::Genre << CategoryId::Artist << CategoryId::Album; 0372 break; 0373 default: 0374 return; 0375 } 0376 0377 m_contentView->setModel( new ScriptableServiceCollectionTreeModel( m_collection, viewLevels ) ); 0378 m_polished = true; 0379 0380 } 0381 0382 infoChanged( m_rootHtml ); 0383 } 0384 0385 void ScriptableService::setCustomEmblem( const QPixmap &emblem ) 0386 { 0387 m_customEmblem = emblem; 0388 } 0389 0390 QPixmap ScriptableService::customEmblem() 0391 { 0392 return m_customEmblem; 0393 } 0394 0395 0396 QString ScriptableService::customScalableEmblem() 0397 { 0398 return m_customScalableEmblem; 0399 } 0400 0401 0402 void ScriptableService::setCustomScalableEmblem ( const QString& emblemPath ) 0403 { 0404 m_customScalableEmblem = emblemPath; 0405 } 0406 0407 0408 0409 void ScriptableService::setCurrentInfo( const QString & info ) 0410 { 0411 infoChanged( info ); 0412 } 0413 0414 0415 0416 0417