~ubuntu-branches/ubuntu/trusty/tomahawk/trusty-proposed

« back to all changes in this revision

Viewing changes to src/sourcetree/items/CategoryItems.cpp

  • Committer: Package Import Robot
  • Author(s): Harald Sitter
  • Date: 2013-03-07 21:50:13 UTC
  • Revision ID: package-import@ubuntu.com-20130307215013-6gdjkdds7i9uenvs
Tags: upstream-0.6.0+dfsg
ImportĀ upstreamĀ versionĀ 0.6.0+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
 
3
 *  Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
 
4
 *
 
5
 *  This program is free software; you can redistribute it and/or modify
 
6
 *  it under the terms of the GNU General Public License as published by
 
7
 *  the Free Software Foundation; either version 2 of the License, or
 
8
 *  (at your option) any later version.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License along
 
16
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 
17
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
18
 */
 
19
 
 
20
#include "CategoryItems.h"
 
21
 
 
22
#include <QMimeData>
 
23
 
 
24
#include <echonest/Playlist.h>
 
25
 
 
26
#include "DropJob.h"
 
27
#include "TomahawkApp.h"
 
28
#include "ViewManager.h"
 
29
#include "ViewPage.h"
 
30
#include "SourceList.h"
 
31
#include "SourceTreeView.h"
 
32
#include "TomahawkWindow.h"
 
33
#include "utils/TomahawkUtils.h"
 
34
#include "playlist/dynamic/GeneratorInterface.h"
 
35
#include "widgets/NewPlaylistWidget.h"
 
36
#include "utils/ImageRegistry.h"
 
37
#include "utils/Logger.h"
 
38
 
 
39
using namespace Tomahawk;
 
40
 
 
41
 
 
42
/// CategoryAddItem
 
43
 
 
44
CategoryAddItem::CategoryAddItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::CategoryType type )
 
45
    : SourceTreeItem( model, parent, SourcesModel::CategoryAdd )
 
46
    , m_categoryType( type )
 
47
{
 
48
}
 
49
 
 
50
 
 
51
CategoryAddItem::~CategoryAddItem()
 
52
{
 
53
}
 
54
 
 
55
 
 
56
QString
 
57
CategoryAddItem::text() const
 
58
{
 
59
    switch( m_categoryType )
 
60
    {
 
61
        case SourcesModel::PlaylistsCategory:
 
62
            return tr( "Create new Playlist" );
 
63
 
 
64
        case SourcesModel::StationsCategory:
 
65
            return tr( "Create new Station" );
 
66
    }
 
67
 
 
68
    return QString();
 
69
}
 
70
 
 
71
 
 
72
void
 
73
CategoryAddItem::activate()
 
74
{
 
75
    switch( m_categoryType )
 
76
    {
 
77
        case SourcesModel::PlaylistsCategory:
 
78
            APP->mainWindow()->createPlaylist();
 
79
            break;
 
80
 
 
81
        case SourcesModel::StationsCategory:
 
82
            APP->mainWindow()->createStation();
 
83
            break;
 
84
    }
 
85
}
 
86
 
 
87
 
 
88
Qt::ItemFlags
 
89
CategoryAddItem::flags() const
 
90
{
 
91
    switch ( m_categoryType )
 
92
    {
 
93
        case SourcesModel::PlaylistsCategory:
 
94
            return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled;
 
95
 
 
96
        case SourcesModel::StationsCategory:
 
97
            return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled;
 
98
 
 
99
        default:
 
100
            return Qt::ItemIsEnabled;
 
101
            break;
 
102
    }
 
103
}
 
104
 
 
105
 
 
106
QIcon
 
107
CategoryAddItem::icon() const
 
108
{
 
109
    return ImageRegistry::instance()->icon( RESPATH "images/add.svg" );
 
110
}
 
111
 
 
112
 
 
113
bool
 
114
CategoryAddItem::willAcceptDrag( const QMimeData* data ) const
 
115
{
 
116
    if ( ( m_categoryType == SourcesModel::PlaylistsCategory || m_categoryType == SourcesModel::StationsCategory ) && DropJob::acceptsMimeData( data ) )
 
117
    {
 
118
        return true;
 
119
    }
 
120
 
 
121
    return false;
 
122
}
 
123
 
 
124
 
 
125
SourceTreeItem::DropTypes
 
126
CategoryAddItem::supportedDropTypes( const QMimeData* data ) const
 
127
{
 
128
    SourceTreeItem::DropTypes types = DropTypesNone;
 
129
 
 
130
    if ( m_categoryType == SourcesModel::PlaylistsCategory )
 
131
    {
 
132
        if ( data->hasFormat( "application/tomahawk.query.list" ) )
 
133
            return types | DropTypeThisTrack | DropTypeThisAlbum | DropTypeAllFromArtist | DropTypeLocalItems | DropTypeTop50;
 
134
        else if ( data->hasFormat( "application/tomahawk.result.list" ) )
 
135
            return types | DropTypeThisTrack | DropTypeThisAlbum | DropTypeAllFromArtist | DropTypeLocalItems | DropTypeTop50;
 
136
        else if ( data->hasFormat( "application/tomahawk.metadata.album" ) )
 
137
            return types | DropTypeThisAlbum | DropTypeAllFromArtist | DropTypeLocalItems | DropTypeTop50;
 
138
        else if ( data->hasFormat( "application/tomahawk.metadata.artist" ) )
 
139
            return types | DropTypeAllFromArtist | DropTypeLocalItems | DropTypeTop50;
 
140
    }
 
141
 
 
142
    return types;
 
143
}
 
144
 
 
145
 
 
146
bool
 
147
CategoryAddItem::dropMimeData( const QMimeData* data, Qt::DropAction )
 
148
{
 
149
    // As DropJob always converts dropped items to query_ptrs for all tracks we need to extract album/artist metadata ourselves for stations
 
150
    if ( m_categoryType == SourcesModel::StationsCategory &&
 
151
         ( data->hasFormat( "application/tomahawk.metadata.artist" ) || data->hasFormat( "application/tomahawk.metadata.album" ) ) )
 
152
    {
 
153
        QByteArray mimeData;
 
154
        if ( data->hasFormat( "application/tomahawk.metadata.artist" ) )
 
155
            mimeData = data->data( "application/tomahawk.metadata.artist" );
 
156
        else if ( data->hasFormat( "application/tomahawk.metadata.album" ) )
 
157
            mimeData = data->data( "application/tomahawk.metadata.album" );
 
158
 
 
159
        QDataStream stream( &mimeData, QIODevice::ReadOnly );
 
160
 
 
161
        dynplaylist_ptr newpl = DynamicPlaylist::create( SourceList::instance()->getLocal(), uuid(), QString(), "", SourceList::instance()->getLocal()->friendlyName(), OnDemand, false );
 
162
        newpl->setMode( OnDemand );
 
163
 
 
164
        QString firstArtist;
 
165
        // now we want to add each artist as a filter...
 
166
        QList< dyncontrol_ptr > contrls;
 
167
        while ( !stream.atEnd() )
 
168
        {
 
169
            QString artist;
 
170
            stream >> artist;
 
171
            if ( firstArtist.isEmpty() )
 
172
                firstArtist = artist;
 
173
 
 
174
            QString album;
 
175
            if ( data->hasFormat( "application/tomahawk.metadata.album" ) )
 
176
                stream >> album; // throw away album title... we only create artists filters for now
 
177
 
 
178
            dyncontrol_ptr c = newpl->generator()->createControl( "Artist" );
 
179
            c->setInput( QString( "%1" ).arg( artist ) );
 
180
            contrls << c;
 
181
        }
 
182
 
 
183
        QString name = firstArtist.isEmpty() ? tr( "New Station" ) : tr( "%1 Station" ).arg( firstArtist );
 
184
        newpl->createNewRevision( uuid(), newpl->currentrevision(), newpl->type(), contrls );
 
185
        newpl->setProperty( "newname", name );
 
186
        connect( newpl.data(), SIGNAL( dynamicRevisionLoaded( Tomahawk::DynamicPlaylistRevision ) ), this, SLOT( playlistToRenameLoaded() ) );
 
187
 
 
188
        ViewManager::instance()->show( newpl );
 
189
        return true;
 
190
    }
 
191
 
 
192
    // This could be needed once echonest supports filtering by album.
 
193
    // If they never will, or if they do and this code still is not used, throw it away!
 
194
    // If you enable this, make sure to remove the checks for album above.
 
195
 
 
196
    /* if ( m_categoryType == SourcesModel::StationsCategory && data->hasFormat( "application/tomahawk.metadata.album" ) )
 
197
    {
 
198
        QByteArray mimeData = data->data( "application/tomahawk.metadata.album" );
 
199
        QDataStream stream( &mimeData, QIODevice::ReadOnly );
 
200
 
 
201
        dynplaylist_ptr newpl = DynamicPlaylist::create( SourceList::instance()->getLocal(), uuid(), QString(), "", SourceList::instance()->getLocal()->friendlyName(), OnDemand, false );
 
202
        newpl->setMode( OnDemand );
 
203
 
 
204
        QString firstAlbum;
 
205
        // now we want to add each artist as a filter...
 
206
        QList< dyncontrol_ptr > contrls;
 
207
        while ( !stream.atEnd() )
 
208
        {
 
209
            QString artist;
 
210
            stream >> artist;
 
211
            QString album;
 
212
            stream >> album;
 
213
 
 
214
            if ( firstAlbum.isEmpty() )
 
215
            {
 
216
                firstAlbum = album;
 
217
            }
 
218
 
 
219
            dyncontrol_ptr c = newpl->generator()->createControl( "Album" );
 
220
            c->setInput( QString( "%1" ).arg( artist ) );
 
221
            contrls << c;
 
222
        }
 
223
 
 
224
        QString name = firstAlbum.isEmpty() ? tr( "New Station" ) : tr( "%1 Station" ).arg( firstAlbum );
 
225
        newpl->rename( name );
 
226
        newpl->createNewRevision( uuid(), newpl->currentrevision(), newpl->type(), contrls );
 
227
 
 
228
        ViewManager::instance()->show( newpl );
 
229
        // Give a shot to try to rename it. The playlist has to be created first. ugly.
 
230
        QTimer::singleShot( 300, APP->mainWindow()->sourceTreeView(), SLOT( renamePlaylist() ) );
 
231
        return true;
 
232
 
 
233
    } */
 
234
 
 
235
    // Create a new playlist seeded with these items
 
236
    DropJob *dj = new DropJob();
 
237
 
 
238
    connect( dj, SIGNAL( tracks( QList< Tomahawk::query_ptr > ) ), this, SLOT( parsedDroppedTracks( QList< Tomahawk::query_ptr > ) ), Qt::QueuedConnection );
 
239
    if ( dropType() == DropTypeAllFromArtist )
 
240
        dj->setGetWholeArtists( true );
 
241
    if ( dropType() == DropTypeThisAlbum )
 
242
        dj->setGetWholeAlbums( true );
 
243
 
 
244
    if ( dropType() == DropTypeLocalItems )
 
245
    {
 
246
        dj->setGetWholeArtists( true );
 
247
        dj->tracksFromMimeData( data, false, true );
 
248
    }
 
249
    else if ( dropType() == DropTypeTop50 )
 
250
    {
 
251
        dj->setGetWholeArtists( true );
 
252
        dj->tracksFromMimeData( data, false, false, true );
 
253
    }
 
254
    else
 
255
        dj->tracksFromMimeData( data, false, false );
 
256
 
 
257
    return true;
 
258
}
 
259
 
 
260
 
 
261
void
 
262
CategoryAddItem::playlistToRenameLoaded()
 
263
{
 
264
    Playlist* pl = qobject_cast< Playlist* >( sender() );
 
265
    Q_ASSERT( pl );
 
266
 
 
267
    QString name = sender()->property( "newname" ).toString();
 
268
    if ( !name.isEmpty() )
 
269
        pl->rename( name );
 
270
    else
 
271
        QTimer::singleShot( 400, APP->mainWindow()->sourceTreeView(), SLOT( renamePlaylist() ) );
 
272
 
 
273
    disconnect( pl, SIGNAL( dynamicRevisionLoaded( Tomahawk::DynamicPlaylistRevision ) ), this, SLOT( playlistToRenameLoaded() ) );
 
274
    disconnect( pl, SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), this, SLOT( playlistToRenameLoaded() ) );
 
275
}
 
276
 
 
277
 
 
278
void
 
279
CategoryAddItem::parsedDroppedTracks( const QList< query_ptr >& tracks )
 
280
{
 
281
    if ( m_categoryType == SourcesModel::PlaylistsCategory )
 
282
    {
 
283
        playlist_ptr newpl = Playlist::create( SourceList::instance()->getLocal(), uuid(), "New Playlist", "", SourceList::instance()->getLocal()->friendlyName(), false, tracks );
 
284
        ViewManager::instance()->show( newpl );
 
285
 
 
286
        connect( newpl.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), this, SLOT( playlistToRenameLoaded() ) );
 
287
    }
 
288
    else if ( m_categoryType == SourcesModel::StationsCategory )
 
289
    {
 
290
        // seed the playlist with these song or artist filters
 
291
        QString name;
 
292
        name = tracks.isEmpty() ? tr( "New Station" ) : tr( "%1 Station" ).arg( tracks.first()->track() );
 
293
 
 
294
        dynplaylist_ptr newpl = DynamicPlaylist::create( SourceList::instance()->getLocal(), uuid(), name, "", SourceList::instance()->getLocal()->friendlyName(), OnDemand, false );
 
295
        newpl->setMode( OnDemand );
 
296
 
 
297
        // now we want to add each query as a song or similar artist filter...
 
298
        QList< dyncontrol_ptr > controls;
 
299
        foreach ( const Tomahawk::query_ptr& q, tracks )
 
300
        {
 
301
            dyncontrol_ptr c = newpl->generator()->createControl( "Song" );
 
302
            c->setInput( QString( "%1 %2" ).arg( q->track() ).arg( q->artist() ) );
 
303
            controls << c;
 
304
        }
 
305
 
 
306
        newpl->createNewRevision( uuid(), newpl->currentrevision(), newpl->type(), controls );
 
307
 
 
308
        ViewManager::instance()->show( newpl );
 
309
        connect( newpl.data(), SIGNAL( dynamicRevisionLoaded( Tomahawk::DynamicPlaylistRevision ) ), this, SLOT( playlistToRenameLoaded() ) );
 
310
    }
 
311
}
 
312
 
 
313
 
 
314
int
 
315
CategoryAddItem::peerSortValue() const
 
316
{
 
317
    return INT_MAX; // after any siblings
 
318
}
 
319
 
 
320
 
 
321
/// CategoryItem
 
322
 
 
323
CategoryItem::CategoryItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::CategoryType category, bool showAddItem )
 
324
    : SourceTreeItem( model, parent, SourcesModel::Category )
 
325
    , m_category( category )
 
326
    , m_addItem( 0 )
 
327
    , m_showAdd( showAddItem )
 
328
{
 
329
    // in the constructor we're still being added to the parent, so we don't exist to have rows addded yet. so this is safe.
 
330
    //     beginRowsAdded( 0, 0 );
 
331
    if ( m_showAdd )
 
332
    {
 
333
        m_addItem = new CategoryAddItem( model, this, m_category );
 
334
    }
 
335
    //     endRowsAdded();
 
336
}
 
337
 
 
338
 
 
339
void
 
340
CategoryItem::insertItem( SourceTreeItem* item )
 
341
{
 
342
    insertItems( QList< SourceTreeItem* >() << item );
 
343
}
 
344
 
 
345
 
 
346
void
 
347
CategoryItem::insertItems( QList< SourceTreeItem* > items )
 
348
{
 
349
    // add the items to the category, and connect to the signals
 
350
    int curCount = children().size();
 
351
    if ( m_showAdd ) // if there's an add item, add it before that
 
352
        curCount--;
 
353
 
 
354
    beginRowsAdded( curCount, curCount + items.size() - 1 );
 
355
    foreach( SourceTreeItem* item, items )
 
356
    {
 
357
        insertChild( children().count() - 1, item );
 
358
    }
 
359
    endRowsAdded();
 
360
}
 
361
 
 
362
 
 
363
int
 
364
CategoryItem::peerSortValue() const
 
365
{
 
366
    if ( m_category == SourcesModel::PlaylistsCategory )
 
367
        return -100;
 
368
    else if ( m_category == SourcesModel::StationsCategory )
 
369
        return 100;
 
370
    else
 
371
        return 0;
 
372
}
 
373
 
 
374
 
 
375
void
 
376
CategoryItem::activate()
 
377
{
 
378
    emit toggleExpandRequest( this );
 
379
}
 
380
 
 
381
 
 
382
QString
 
383
CategoryItem::text() const
 
384
{
 
385
    switch( m_category )
 
386
    {
 
387
    case SourcesModel::PlaylistsCategory:
 
388
        return tr( "Playlists" );
 
389
    case SourcesModel::StationsCategory:
 
390
        return tr( "Stations" );
 
391
    }
 
392
    return QString();
 
393
}
 
394
 
 
395
 
 
396
Qt::ItemFlags
 
397
CategoryItem::flags() const
 
398
{
 
399
    return Qt::ItemIsEnabled;
 
400
}
 
401
 
 
402
 
 
403
SourcesModel::CategoryType
 
404
CategoryItem::categoryType()
 
405
{
 
406
    return m_category;
 
407
}