File indexing completed on 2024-05-05 16:54:08

0001 /****************************************************************************************
0002  * Copyright (c) 2007 Maximilian Kossick <maximilian.kossick@googlemail.com>            *
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 "AmarokMimeData.h"
0018 
0019 #include "core/collections/QueryMaker.h"
0020 #include "core/support/Debug.h"
0021 
0022 #include <QCoreApplication>
0023 #include <QList>
0024 #include <QTimer>
0025 #include <QUrl>
0026 
0027 const QString AmarokMimeData::TRACK_MIME = QStringLiteral("application/x-amarok-tracks");
0028 const QString AmarokMimeData::PLAYLIST_MIME = QStringLiteral("application/x-amarok-playlists");
0029 const QString AmarokMimeData::PLAYLISTBROWSERGROUP_MIME = QStringLiteral("application/x-amarok-playlistbrowsergroup");
0030 const QString AmarokMimeData::PODCASTCHANNEL_MIME = QStringLiteral("application/x-amarok-podcastchannel");
0031 const QString AmarokMimeData::PODCASTEPISODE_MIME = QStringLiteral("application/x-amarok-podcastepisode");
0032 const QString AmarokMimeData::AMAROKURL_MIME = QStringLiteral("application/x-amarok-amarokurl");
0033 const QString AmarokMimeData::BOOKMARKGROUP_MIME = QStringLiteral("application/x-amarok-bookmarkgroup");
0034 
0035 
0036 class AmarokMimeData::Private
0037 {
0038 public:
0039     Private() : deleteQueryMakers( true ), completedQueries( 0 )
0040     {}
0041 
0042     ~Private()
0043     {
0044         if( deleteQueryMakers )
0045             qDeleteAll( queryMakers );
0046     }
0047 
0048     Meta::TrackList tracks;
0049     Playlists::PlaylistList playlists;
0050     QStringList playlistGroups;
0051     Podcasts::PodcastChannelList m_podcastChannels;
0052     Podcasts::PodcastEpisodeList m_podcastEpisodes;
0053     QList<Collections::QueryMaker*> queryMakers;
0054     QMap<Collections::QueryMaker*, Meta::TrackList> trackMap;
0055     QMap<Collections::QueryMaker*, Playlists::PlaylistList> playlistMap;
0056     BookmarkList bookmarks;
0057     BookmarkGroupList bookmarkGroups;
0058 
0059     bool deleteQueryMakers;
0060     int completedQueries;
0061 
0062 };
0063 
0064 AmarokMimeData::AmarokMimeData()
0065     : QMimeData()
0066     , d( new Private() )
0067 {
0068     //nothing to do
0069 }
0070 
0071 AmarokMimeData::~AmarokMimeData()
0072 {
0073     delete d;
0074 }
0075 
0076 QStringList
0077 AmarokMimeData::formats() const
0078 {
0079     QStringList formats( QMimeData::formats() );
0080     if( !d->tracks.isEmpty() || !d->queryMakers.isEmpty() || !d->playlistGroups.isEmpty() || !d->bookmarks.isEmpty() || !d->bookmarkGroups.isEmpty() )
0081     {
0082         formats.append( TRACK_MIME );
0083         formats.append( PLAYLIST_MIME );
0084         formats.append( PLAYLISTBROWSERGROUP_MIME );
0085         formats.append( PODCASTCHANNEL_MIME );
0086         formats.append( PODCASTEPISODE_MIME );
0087         formats.append( BOOKMARKGROUP_MIME );
0088         formats.append( AMAROKURL_MIME );
0089 
0090         if( !formats.contains( QStringLiteral("text/uri-list") ) )
0091             formats.append( QStringLiteral("text/uri-list") );
0092         if( !formats.contains( QStringLiteral("text/plain") ) )
0093             formats.append( QStringLiteral("text/plain") );
0094     }
0095 
0096     return formats;
0097 }
0098 
0099 bool
0100 AmarokMimeData::hasFormat( const QString &mimeType ) const
0101 {
0102     if( mimeType == TRACK_MIME )
0103         return !d->tracks.isEmpty() || !d->queryMakers.isEmpty();
0104     else if( mimeType == PLAYLIST_MIME )
0105         return !d->playlists.isEmpty() || !d->queryMakers.isEmpty();
0106     else if( mimeType == PLAYLISTBROWSERGROUP_MIME )
0107         return !d->playlistGroups.isEmpty();
0108     else if( mimeType == PODCASTCHANNEL_MIME )
0109         return !d->m_podcastChannels.isEmpty();
0110     else if( mimeType == PODCASTEPISODE_MIME )
0111         return !d->m_podcastEpisodes.isEmpty();
0112     else if( mimeType == BOOKMARKGROUP_MIME )
0113         return !d->bookmarkGroups.isEmpty();
0114     else if( mimeType == AMAROKURL_MIME )
0115         return !d->bookmarks.isEmpty();
0116     else if( mimeType == QLatin1String("text/uri-list") || mimeType == QLatin1String("text/plain") )
0117         return !d->tracks.isEmpty() || !d->playlists.isEmpty()
0118             || !d->m_podcastChannels.isEmpty() || !d->m_podcastEpisodes.isEmpty()
0119             || !d->queryMakers.isEmpty();
0120     else
0121         return QMimeData::hasFormat( mimeType );
0122 }
0123 
0124 Meta::TrackList
0125 AmarokMimeData::tracks() const
0126 {
0127     while( d->completedQueries < d->queryMakers.count() )
0128     {
0129         QCoreApplication::instance()->processEvents( QEventLoop::ExcludeUserInputEvents );
0130     }
0131     Meta::TrackList result = d->tracks;
0132     foreach( Collections::QueryMaker *qm, d->queryMakers )
0133     {
0134         if( d->trackMap.contains( qm ) )
0135             result << d->trackMap.value( qm );
0136     }
0137     return result;
0138 }
0139 
0140 void
0141 AmarokMimeData::setTracks( const Meta::TrackList &tracks )
0142 {
0143     d->tracks = tracks;
0144 }
0145 
0146 void
0147 AmarokMimeData::addTracks( const Meta::TrackList &tracks )
0148 {
0149     d->tracks << tracks;
0150 }
0151 
0152 void
0153 AmarokMimeData::getTrackListSignal() const
0154 {
0155     if( d->completedQueries < d->queryMakers.count() )
0156     {
0157         QTimer::singleShot( 0, this, &AmarokMimeData::getTrackListSignal );
0158         return;
0159     }
0160     else
0161     {
0162         Meta::TrackList result = d->tracks;
0163         foreach( Collections::QueryMaker *qm, d->queryMakers )
0164         {
0165             if( d->trackMap.contains( qm ) )
0166                 result << d->trackMap.value( qm );
0167         }
0168         Q_EMIT trackListSignal( result );
0169     }
0170 }
0171 
0172 Playlists::PlaylistList
0173 AmarokMimeData::playlists() const
0174 {
0175     while( d->completedQueries < d->queryMakers.count() )
0176     {
0177         QCoreApplication::instance()->processEvents( QEventLoop::AllEvents );
0178     }
0179     Playlists::PlaylistList result = d->playlists;
0180     return result;
0181 }
0182 
0183 void
0184 AmarokMimeData::setPlaylists( const Playlists::PlaylistList &playlists )
0185 {
0186     d->playlists = playlists;
0187 }
0188 
0189 void
0190 AmarokMimeData::addPlaylists( const Playlists::PlaylistList &playlists )
0191 {
0192     d->playlists << playlists;
0193 }
0194 
0195 QStringList
0196 AmarokMimeData::playlistGroups() const
0197 {
0198     return d->playlistGroups;
0199 }
0200 
0201 void
0202 AmarokMimeData::setPlaylistGroups( const QStringList &groups )
0203 {
0204     d->playlistGroups = groups;
0205 }
0206 
0207 void
0208 AmarokMimeData::addPlaylistGroup( const QString &group )
0209 {
0210     d->playlistGroups << group;
0211 }
0212 
0213 Podcasts::PodcastChannelList
0214 AmarokMimeData::podcastChannels() const
0215 {
0216     return d->m_podcastChannels;
0217 }
0218 
0219 void
0220 AmarokMimeData::setPodcastChannels( const Podcasts::PodcastChannelList &channels )
0221 {
0222     d->m_podcastChannels = channels;
0223 }
0224 
0225 void
0226 AmarokMimeData::addPodcastChannels( const Podcasts::PodcastChannelList &channels )
0227 {
0228     d->m_podcastChannels << channels;
0229 }
0230 
0231 Podcasts::PodcastEpisodeList
0232 AmarokMimeData::podcastEpisodes() const
0233 {
0234     return d->m_podcastEpisodes;
0235 }
0236 
0237 void
0238 AmarokMimeData::setPodcastEpisodes( const Podcasts::PodcastEpisodeList &episodes )
0239 {
0240     d->m_podcastEpisodes = episodes;
0241 }
0242 
0243 void
0244 AmarokMimeData::addPodcastEpisodes( const Podcasts::PodcastEpisodeList &episodes )
0245 {
0246     d->m_podcastEpisodes << episodes;
0247 }
0248 
0249 QList<Collections::QueryMaker*>
0250 AmarokMimeData::queryMakers()
0251 {
0252     d->deleteQueryMakers = false;
0253     return d->queryMakers;
0254 }
0255 
0256 void
0257 AmarokMimeData::addQueryMaker( Collections::QueryMaker *queryMaker )
0258 {
0259     d->queryMakers.append( queryMaker );
0260 }
0261 
0262 void
0263 AmarokMimeData::setQueryMakers( const QList<Collections::QueryMaker*> &queryMakers )
0264 {
0265     d->queryMakers << queryMakers;
0266 }
0267 
0268 BookmarkList AmarokMimeData::bookmarks() const
0269 {
0270     return d->bookmarks;
0271 }
0272 
0273 void AmarokMimeData::setBookmarks( const BookmarkList &bookmarks )
0274 {
0275     d->bookmarks = bookmarks;
0276 }
0277 
0278 void AmarokMimeData::addBookmarks( const BookmarkList &bookmarks )
0279 {
0280     d->bookmarks << bookmarks;
0281 }
0282 
0283 BookmarkGroupList AmarokMimeData::bookmarkGroups() const
0284 {
0285     return d->bookmarkGroups;
0286 }
0287 
0288 void AmarokMimeData::setBookmarkGroups( const BookmarkGroupList &groups )
0289 {
0290     d->bookmarkGroups = groups;
0291 }
0292 
0293 void AmarokMimeData::addBookmarkGroups( const BookmarkGroupList &groups )
0294 {
0295     d->bookmarkGroups << groups;
0296 }
0297 
0298 QVariant
0299 AmarokMimeData::retrieveData( const QString &mimeType, QVariant::Type type ) const
0300 {
0301     Meta::TrackList tracks = this->tracks();
0302     Playlists::PlaylistList playlists = this->playlists();
0303     Podcasts::PodcastChannelList channels = this->podcastChannels();
0304     Podcasts::PodcastEpisodeList episodes = this->podcastEpisodes();
0305     if( !tracks.isEmpty() )
0306     {
0307         if( mimeType == QLatin1String("text/uri-list") && (type == QVariant::List || type == QVariant::ByteArray) )
0308         {
0309             QList<QVariant> list;
0310             foreach( Meta::TrackPtr track, tracks )
0311             {
0312                 list.append( QVariant( QUrl( track->playableUrl() ) ) );
0313             }
0314             foreach( Podcasts::PodcastEpisodePtr episode, episodes )
0315             {
0316                 list.append( QVariant( QUrl( episode->playableUrl() ) ) );
0317             }
0318             foreach( Playlists::PlaylistPtr playlist, playlists )
0319             {
0320                 list.append( QVariant( QUrl( playlist->uidUrl() ) ) );
0321             }
0322             foreach( Podcasts::PodcastChannelPtr channel, channels )
0323             {
0324                 list.append( QVariant( QUrl( channel->url() ) ) );
0325             }
0326             return QVariant( list );
0327         }
0328         if( mimeType == QLatin1String("text/plain") && (type == QVariant::String || type == QVariant::ByteArray) )
0329         {
0330             QString result;
0331             foreach( Meta::TrackPtr track, tracks )
0332             {
0333                 if( !result.isEmpty() )
0334                     result += '\n';
0335                 result += track->artist()->prettyName();
0336                 result += QLatin1String(" - ");
0337                 result += track->prettyName();
0338             }
0339             foreach( Podcasts::PodcastEpisodePtr episode, episodes )
0340             {
0341                 if( !result.isEmpty() )
0342                     result += '\n';
0343                 result += episode->prettyName();
0344                 result += QLatin1String(" - ");
0345                 result += episode->channel()->prettyName();
0346             }
0347             foreach( Playlists::PlaylistPtr playlist, playlists )
0348             {
0349                 if( !result.isEmpty() )
0350                     result += '\n';
0351                 result += playlist->prettyName();
0352             }
0353             foreach( Podcasts::PodcastChannelPtr channel, channels )
0354             {
0355                 if( !result.isEmpty() )
0356                     result += '\n';
0357                 result += channel->prettyName();
0358             }
0359             return QVariant( result );
0360         }
0361     }
0362     return QMimeData::retrieveData( mimeType, type );
0363 }
0364 
0365 void
0366 AmarokMimeData::startQueries()
0367 {
0368     foreach( Collections::QueryMaker *qm, d->queryMakers )
0369     {
0370         qm->setQueryType( Collections::QueryMaker::Track );
0371         connect( qm, &Collections::QueryMaker::newTracksReady,
0372                  this, &AmarokMimeData::newResultReady, Qt::QueuedConnection );
0373         connect( qm, &Collections::QueryMaker::queryDone, this, &AmarokMimeData::queryDone, Qt::QueuedConnection );
0374         qm->run();
0375     }
0376 }
0377 
0378 void
0379 AmarokMimeData::newResultReady( const Meta::TrackList &tracks )
0380 {
0381     Collections::QueryMaker *qm = dynamic_cast<Collections::QueryMaker*>( sender() );
0382     if( qm )
0383     {
0384         d->trackMap.insert( qm, tracks );
0385     }
0386     else
0387         d->tracks << tracks;
0388 }
0389 
0390 void
0391 AmarokMimeData::queryDone()
0392 {
0393     d->completedQueries++;
0394 }
0395 
0396