1
/****************************************************************************************
2
 * Copyright (c) 2007 Maximilian Kossick <maximilian.kossick@googlemail.com>            *
3
 *                                                                                      *
4
 * This program is free software; you can redistribute it and/or modify it under        *
5
 * the terms of the GNU General Public License as published by the Free Software        *
6
 * Foundation; either version 2 of the License, or (at your option) any later           *
7
 * version.                                                                             *
8
 *                                                                                      *
9
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
10
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
11
 * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
12
 *                                                                                      *
13
 * You should have received a copy of the GNU General Public License along with         *
14
 * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
15
 ****************************************************************************************/
16
17
#include "AmarokMimeData.h"
18
19
#include "core/support/Debug.h"
20
21
#include <QCoreApplication>
22
#include <QList>
23
#include <QTimer>
24
#include <QUrl>
25
26
const QString AmarokMimeData::TRACK_MIME = "application/x-amarok-tracks";
27
const QString AmarokMimeData::PLAYLIST_MIME = "application/x-amarok-playlists";
28
const QString AmarokMimeData::PLAYLISTBROWSERGROUP_MIME = "application/x-amarok-playlistbrowsergroup";
29
const QString AmarokMimeData::PODCASTCHANNEL_MIME = "application/x-amarok-podcastchannel";
30
const QString AmarokMimeData::PODCASTEPISODE_MIME = "application/x-amarok-podcastepisode";
31
const QString AmarokMimeData::AMAROKURL_MIME = "application/x-amarok-amarokurl";
32
const QString AmarokMimeData::BOOKMARKGROUP_MIME = "application/x-amarok-bookmarkgroup";
33
34
35
class AmarokMimeData::Private
36
{
37
public:
38
    Private() : deleteQueryMakers( true ), completedQueries( 0 )
39
    {}
40
41
    ~Private()
42
    {
43
        if( deleteQueryMakers )
44
            qDeleteAll( queryMakers );
45
    }
46
47
    Meta::TrackList tracks;
48
    Playlists::PlaylistList playlists;
49
    QStringList playlistGroups;
50
    Podcasts::PodcastChannelList m_podcastChannels;
51
    Podcasts::PodcastEpisodeList m_podcastEpisodes;
52
    QList<Collections::QueryMaker*> queryMakers;
53
    QMap<Collections::QueryMaker*, Meta::TrackList> trackMap;
54
    QMap<Collections::QueryMaker*, Playlists::PlaylistList> playlistMap;
55
    BookmarkList bookmarks;
56
    BookmarkGroupList bookmarkGroups;
57
58
    bool deleteQueryMakers;
59
    int completedQueries;
60
61
};
62
63
AmarokMimeData::AmarokMimeData()
64
    : QMimeData()
65
    , d( new Private() )
66
{
67
    //nothing to do
68
}
69
70
AmarokMimeData::~AmarokMimeData()
71
{
72
    delete d;
73
}
74
75
QStringList
76
AmarokMimeData::formats() const
77
{
78
    QStringList formats( QMimeData::formats() );
79
    if( !d->tracks.isEmpty() || !d->queryMakers.isEmpty() || !d->playlistGroups.isEmpty() || !d->bookmarks.isEmpty() || !d->bookmarkGroups.isEmpty() )
80
    {
81
        formats.append( TRACK_MIME );
82
        formats.append( PLAYLIST_MIME );
83
        formats.append( PLAYLISTBROWSERGROUP_MIME );
84
        formats.append( PODCASTCHANNEL_MIME );
85
        formats.append( PODCASTEPISODE_MIME );
86
        formats.append( BOOKMARKGROUP_MIME );
87
        formats.append( AMAROKURL_MIME );
88
89
        if( !formats.contains( "text/uri-list" ) )
90
            formats.append( "text/uri-list" );
91
        if( !formats.contains( "text/plain" ) )
92
            formats.append( "text/plain" );
93
    }
94
95
    return formats;
96
}
97
98
bool
99
AmarokMimeData::hasFormat( const QString &mimeType ) const
100
{
101
    if( mimeType == TRACK_MIME )
102
        return !d->tracks.isEmpty() || !d->queryMakers.isEmpty();
103
    else if( mimeType == PLAYLIST_MIME )
104
        return !d->playlists.isEmpty() || !d->queryMakers.isEmpty();
105
    else if( mimeType == PLAYLISTBROWSERGROUP_MIME )
106
        return !d->playlistGroups.isEmpty();
107
    else if( mimeType == PODCASTCHANNEL_MIME )
108
        return !d->m_podcastChannels.isEmpty();
109
    else if( mimeType == PODCASTEPISODE_MIME )
110
        return !d->m_podcastEpisodes.isEmpty();
111
    else if( mimeType == BOOKMARKGROUP_MIME )
112
        return !d->bookmarkGroups.isEmpty();
113
    else if( mimeType == AMAROKURL_MIME )
114
        return !d->bookmarks.isEmpty();
115
    else if( mimeType == "text/uri-list" || mimeType == "text/plain" )
116
        return !d->tracks.isEmpty() || !d->playlists.isEmpty()
117
            || !d->m_podcastChannels.isEmpty() || !d->m_podcastEpisodes.isEmpty()
118
            || !d->queryMakers.isEmpty();
119
    else
120
        return QMimeData::hasFormat( mimeType );
121
}
122
123
Meta::TrackList
124
AmarokMimeData::tracks() const
125
{
126
    while( d->completedQueries < d->queryMakers.count() )
127
    {
128
        QCoreApplication::instance()->processEvents( QEventLoop::AllEvents );
129
    }
130
    Meta::TrackList result = d->tracks;
131
    foreach( Collections::QueryMaker *qm, d->queryMakers )
132
    {
133
        if( d->trackMap.contains( qm ) )
134
            result << d->trackMap.value( qm );
135
    }
136
    return result;
137
}
138
139
void
140
AmarokMimeData::setTracks( const Meta::TrackList &tracks )
141
{
142
    d->tracks = tracks;
143
}
144
145
void
146
AmarokMimeData::addTracks( const Meta::TrackList &tracks )
147
{
148
    d->tracks << tracks;
149
}
150
151
void
152
AmarokMimeData::getTrackListSignal() const
153
{
154
    if( d->completedQueries < d->queryMakers.count() )
155
    {
156
        QTimer::singleShot( 0, const_cast<AmarokMimeData*>( this ), SLOT( getTrackListSignal() ) );
157
        return;
158
    }
159
    else
160
    {
161
        Meta::TrackList result = d->tracks;
162
        foreach( Collections::QueryMaker *qm, d->queryMakers )
163
        {
164
            if( d->trackMap.contains( qm ) )
165
                result << d->trackMap.value( qm );
166
        }
167
        emit trackListSignal( result );
168
    }
169
}
170
171
Playlists::PlaylistList
172
AmarokMimeData::playlists() const
173
{
174
    while( d->completedQueries < d->queryMakers.count() )
175
    {
176
        QCoreApplication::instance()->processEvents( QEventLoop::AllEvents );
177
    }
178
    Playlists::PlaylistList result = d->playlists;
179
    return result;
180
}
181
182
void
183
AmarokMimeData::setPlaylists( const Playlists::PlaylistList &playlists )
184
{
185
    d->playlists = playlists;
186
}
187
188
void
189
AmarokMimeData::addPlaylists( const Playlists::PlaylistList &playlists )
190
{
191
    d->playlists << playlists;
192
}
193
194
QStringList
195
AmarokMimeData::playlistGroups() const
196
{
197
    return d->playlistGroups;
198
}
199
200
void
201
AmarokMimeData::setPlaylistGroups( const QStringList &groups )
202
{
203
    d->playlistGroups = groups;
204
}
205
206
void
207
AmarokMimeData::addPlaylistGroup( const QString &group )
208
{
209
    d->playlistGroups << group;
210
}
211
212
Podcasts::PodcastChannelList
213
AmarokMimeData::podcastChannels() const
214
{
215
    return d->m_podcastChannels;
216
}
217
218
void
219
AmarokMimeData::setPodcastChannels( const Podcasts::PodcastChannelList &channels )
220
{
221
    d->m_podcastChannels = channels;
222
}
223
224
void
225
AmarokMimeData::addPodcastChannels( const Podcasts::PodcastChannelList &channels )
226
{
227
    d->m_podcastChannels << channels;
228
}
229
230
Podcasts::PodcastEpisodeList
231
AmarokMimeData::podcastEpisodes() const
232
{
233
    return d->m_podcastEpisodes;
234
}
235
236
void
237
AmarokMimeData::setPodcastEpisodes( const Podcasts::PodcastEpisodeList &episodes )
238
{
239
    d->m_podcastEpisodes = episodes;
240
}
241
242
void
243
AmarokMimeData::addPodcastEpisodes( const Podcasts::PodcastEpisodeList &episodes )
244
{
245
    d->m_podcastEpisodes << episodes;
246
}
247
248
QList<Collections::QueryMaker*>
249
AmarokMimeData::queryMakers()
250
{
251
    d->deleteQueryMakers = false;
252
    return d->queryMakers;
253
}
254
255
void
256
AmarokMimeData::addQueryMaker( Collections::QueryMaker *queryMaker )
257
{
258
    d->queryMakers.append( queryMaker );
259
}
260
261
void
262
AmarokMimeData::setQueryMakers( const QList<Collections::QueryMaker*> &queryMakers )
263
{
264
    d->queryMakers << queryMakers;
265
}
266
267
BookmarkList AmarokMimeData::bookmarks() const
268
{
269
    return d->bookmarks;
270
}
271
272
void AmarokMimeData::setBookmarks( const BookmarkList &bookmarks )
273
{
274
    d->bookmarks = bookmarks;
275
}
276
277
void AmarokMimeData::addBookmarks( const BookmarkList &bookmarks )
278
{
279
    d->bookmarks << bookmarks;
280
}
281
282
BookmarkGroupList AmarokMimeData::bookmarkGroups() const
283
{
284
    return d->bookmarkGroups;
285
}
286
287
void AmarokMimeData::setBookmarkGroups( const BookmarkGroupList &groups )
288
{
289
    d->bookmarkGroups = groups;
290
}
291
292
void AmarokMimeData::addBookmarkGroups( const BookmarkGroupList &groups )
293
{
294
    d->bookmarkGroups << groups;
295
}
296
297
QVariant
298
AmarokMimeData::retrieveData( const QString &mimeType, QVariant::Type type ) const
299
{
300
    Meta::TrackList tracks = this->tracks();
301
    Playlists::PlaylistList playlists = this->playlists();
302
    Podcasts::PodcastChannelList channels = this->podcastChannels();
303
    Podcasts::PodcastEpisodeList episodes = this->podcastEpisodes();
304
    if( !tracks.isEmpty() )
305
    {
306
        if( mimeType == "text/uri-list" && (type == QVariant::List || type == QVariant::ByteArray) )
307
        {
308
            QList<QVariant> list;
309
            foreach( Meta::TrackPtr track, tracks )
310
            {
311
                list.append( QVariant( QUrl( track->playableUrl() ) ) );
312
            }
313
            foreach( Podcasts::PodcastEpisodePtr episode, episodes )
314
            {
315
                list.append( QVariant( QUrl( episode->playableUrl() ) ) );
316
            }
317
            foreach( Playlists::PlaylistPtr playlist, playlists )
318
            {
319
                list.append( QVariant( QUrl( playlist->uidUrl() ) ) );
320
            }
321
            foreach( Podcasts::PodcastChannelPtr channel, channels )
322
            {
323
                list.append( QVariant( QUrl( channel->url() ) ) );
324
            }
325
            return QVariant( list );
326
        }
327
        if( mimeType == "text/plain" && (type == QVariant::String || type == QVariant::ByteArray) )
328
        {
329
            QString result;
330
            foreach( Meta::TrackPtr track, tracks )
331
            {
332
                if( !result.isEmpty() )
333
                    result += '\n';
334
                result += track->artist()->prettyName();
335
                result += " - ";
336
                result += track->prettyName();
337
            }
338
            foreach( Podcasts::PodcastEpisodePtr episode, episodes )
339
            {
340
                if( !result.isEmpty() )
341
                    result += '\n';
342
                result += episode->prettyName();
343
                result += " - ";
344
                result += episode->channel()->prettyName();
345
            }
346
            foreach( Playlists::PlaylistPtr playlist, playlists )
347
            {
348
                if( !result.isEmpty() )
349
                    result += '\n';
350
                result += playlist->prettyName();
351
            }
352
            foreach( Podcasts::PodcastChannelPtr channel, channels )
353
            {
354
                if( !result.isEmpty() )
355
                    result += '\n';
356
                result += channel->prettyName();
357
            }
358
            return QVariant( result );
359
        }
360
    }
361
    return QMimeData::retrieveData( mimeType, type );
362
}
363
364
void
365
AmarokMimeData::startQueries()
366
{
367
    foreach( Collections::QueryMaker *qm, d->queryMakers )
368
    {
369
        qm->setQueryType( Collections::QueryMaker::Track );
370
        connect( qm, SIGNAL( newResultReady( QString, Meta::TrackList ) ), this, SLOT( newResultReady( QString, Meta::TrackList ) ), Qt::QueuedConnection );
371
        connect( qm, SIGNAL( queryDone() ), this, SLOT( queryDone() ), Qt::QueuedConnection );
372
        qm->run();
373
    }
374
}
375
376
void
377
AmarokMimeData::newResultReady( const QString &collectionId, const Meta::TrackList &tracks )
378
{
379
    Q_UNUSED( collectionId )
380
    Collections::QueryMaker *qm = dynamic_cast<Collections::QueryMaker*>( sender() );
381
    if( qm )
382
    {
383
        d->trackMap.insert( qm, tracks );
384
    }
385
    else
386
        d->tracks << tracks;
387
}
388
389
void
390
AmarokMimeData::queryDone()
391
{
392
    d->completedQueries++;
393
}
394
395
396
#include "AmarokMimeData.moc"