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