2
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
3
* Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
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.
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.
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.
20
#include "CategoryItems.h"
24
#include <echonest/Playlist.h>
27
#include "TomahawkApp.h"
28
#include "ViewManager.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"
39
using namespace Tomahawk;
44
CategoryAddItem::CategoryAddItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::CategoryType type )
45
: SourceTreeItem( model, parent, SourcesModel::CategoryAdd )
46
, m_categoryType( type )
51
CategoryAddItem::~CategoryAddItem()
57
CategoryAddItem::text() const
59
switch( m_categoryType )
61
case SourcesModel::PlaylistsCategory:
62
return tr( "Create new Playlist" );
64
case SourcesModel::StationsCategory:
65
return tr( "Create new Station" );
73
CategoryAddItem::activate()
75
switch( m_categoryType )
77
case SourcesModel::PlaylistsCategory:
78
APP->mainWindow()->createPlaylist();
81
case SourcesModel::StationsCategory:
82
APP->mainWindow()->createStation();
89
CategoryAddItem::flags() const
91
switch ( m_categoryType )
93
case SourcesModel::PlaylistsCategory:
94
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled;
96
case SourcesModel::StationsCategory:
97
return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled;
100
return Qt::ItemIsEnabled;
107
CategoryAddItem::icon() const
109
return ImageRegistry::instance()->icon( RESPATH "images/add.svg" );
114
CategoryAddItem::willAcceptDrag( const QMimeData* data ) const
116
if ( ( m_categoryType == SourcesModel::PlaylistsCategory || m_categoryType == SourcesModel::StationsCategory ) && DropJob::acceptsMimeData( data ) )
125
SourceTreeItem::DropTypes
126
CategoryAddItem::supportedDropTypes( const QMimeData* data ) const
128
SourceTreeItem::DropTypes types = DropTypesNone;
130
if ( m_categoryType == SourcesModel::PlaylistsCategory )
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;
147
CategoryAddItem::dropMimeData( const QMimeData* data, Qt::DropAction )
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" ) ) )
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" );
159
QDataStream stream( &mimeData, QIODevice::ReadOnly );
161
dynplaylist_ptr newpl = DynamicPlaylist::create( SourceList::instance()->getLocal(), uuid(), QString(), "", SourceList::instance()->getLocal()->friendlyName(), OnDemand, false );
162
newpl->setMode( OnDemand );
165
// now we want to add each artist as a filter...
166
QList< dyncontrol_ptr > contrls;
167
while ( !stream.atEnd() )
171
if ( firstArtist.isEmpty() )
172
firstArtist = artist;
175
if ( data->hasFormat( "application/tomahawk.metadata.album" ) )
176
stream >> album; // throw away album title... we only create artists filters for now
178
dyncontrol_ptr c = newpl->generator()->createControl( "Artist" );
179
c->setInput( QString( "%1" ).arg( artist ) );
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() ) );
188
ViewManager::instance()->show( newpl );
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.
196
/* if ( m_categoryType == SourcesModel::StationsCategory && data->hasFormat( "application/tomahawk.metadata.album" ) )
198
QByteArray mimeData = data->data( "application/tomahawk.metadata.album" );
199
QDataStream stream( &mimeData, QIODevice::ReadOnly );
201
dynplaylist_ptr newpl = DynamicPlaylist::create( SourceList::instance()->getLocal(), uuid(), QString(), "", SourceList::instance()->getLocal()->friendlyName(), OnDemand, false );
202
newpl->setMode( OnDemand );
205
// now we want to add each artist as a filter...
206
QList< dyncontrol_ptr > contrls;
207
while ( !stream.atEnd() )
214
if ( firstAlbum.isEmpty() )
219
dyncontrol_ptr c = newpl->generator()->createControl( "Album" );
220
c->setInput( QString( "%1" ).arg( artist ) );
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 );
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() ) );
235
// Create a new playlist seeded with these items
236
DropJob *dj = new DropJob();
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 );
244
if ( dropType() == DropTypeLocalItems )
246
dj->setGetWholeArtists( true );
247
dj->tracksFromMimeData( data, false, true );
249
else if ( dropType() == DropTypeTop50 )
251
dj->setGetWholeArtists( true );
252
dj->tracksFromMimeData( data, false, false, true );
255
dj->tracksFromMimeData( data, false, false );
262
CategoryAddItem::playlistToRenameLoaded()
264
Playlist* pl = qobject_cast< Playlist* >( sender() );
267
QString name = sender()->property( "newname" ).toString();
268
if ( !name.isEmpty() )
271
QTimer::singleShot( 400, APP->mainWindow()->sourceTreeView(), SLOT( renamePlaylist() ) );
273
disconnect( pl, SIGNAL( dynamicRevisionLoaded( Tomahawk::DynamicPlaylistRevision ) ), this, SLOT( playlistToRenameLoaded() ) );
274
disconnect( pl, SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), this, SLOT( playlistToRenameLoaded() ) );
279
CategoryAddItem::parsedDroppedTracks( const QList< query_ptr >& tracks )
281
if ( m_categoryType == SourcesModel::PlaylistsCategory )
283
playlist_ptr newpl = Playlist::create( SourceList::instance()->getLocal(), uuid(), "New Playlist", "", SourceList::instance()->getLocal()->friendlyName(), false, tracks );
284
ViewManager::instance()->show( newpl );
286
connect( newpl.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), this, SLOT( playlistToRenameLoaded() ) );
288
else if ( m_categoryType == SourcesModel::StationsCategory )
290
// seed the playlist with these song or artist filters
292
name = tracks.isEmpty() ? tr( "New Station" ) : tr( "%1 Station" ).arg( tracks.first()->track() );
294
dynplaylist_ptr newpl = DynamicPlaylist::create( SourceList::instance()->getLocal(), uuid(), name, "", SourceList::instance()->getLocal()->friendlyName(), OnDemand, false );
295
newpl->setMode( OnDemand );
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 )
301
dyncontrol_ptr c = newpl->generator()->createControl( "Song" );
302
c->setInput( QString( "%1 %2" ).arg( q->track() ).arg( q->artist() ) );
306
newpl->createNewRevision( uuid(), newpl->currentrevision(), newpl->type(), controls );
308
ViewManager::instance()->show( newpl );
309
connect( newpl.data(), SIGNAL( dynamicRevisionLoaded( Tomahawk::DynamicPlaylistRevision ) ), this, SLOT( playlistToRenameLoaded() ) );
315
CategoryAddItem::peerSortValue() const
317
return INT_MAX; // after any siblings
323
CategoryItem::CategoryItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::CategoryType category, bool showAddItem )
324
: SourceTreeItem( model, parent, SourcesModel::Category )
325
, m_category( category )
327
, m_showAdd( showAddItem )
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 );
333
m_addItem = new CategoryAddItem( model, this, m_category );
340
CategoryItem::insertItem( SourceTreeItem* item )
342
insertItems( QList< SourceTreeItem* >() << item );
347
CategoryItem::insertItems( QList< SourceTreeItem* > items )
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
354
beginRowsAdded( curCount, curCount + items.size() - 1 );
355
foreach( SourceTreeItem* item, items )
357
insertChild( children().count() - 1, item );
364
CategoryItem::peerSortValue() const
366
if ( m_category == SourcesModel::PlaylistsCategory )
368
else if ( m_category == SourcesModel::StationsCategory )
376
CategoryItem::activate()
378
emit toggleExpandRequest( this );
383
CategoryItem::text() const
387
case SourcesModel::PlaylistsCategory:
388
return tr( "Playlists" );
389
case SourcesModel::StationsCategory:
390
return tr( "Stations" );
397
CategoryItem::flags() const
399
return Qt::ItemIsEnabled;
403
SourcesModel::CategoryType
404
CategoryItem::categoryType()