From a8d8a485e537edc078c49ffaa78bede03a7a7fa6 Mon Sep 17 00:00:00 2001 From: Leo Franchi Date: Thu, 21 Apr 2011 23:29:05 -0400 Subject: [PATCH] Add support for stations and automatic playlists back to the sourcetree don't look at this commit for too long or some parts might cause your eyes to fall out of your head. i apoligize in advance. --- src/libtomahawk/CMakeLists.txt | 6 +- src/libtomahawk/collection.cpp | 98 ++++++- src/libtomahawk/collection.h | 36 ++- .../database/databasecollection.cpp | 68 +++-- src/libtomahawk/database/databasecollection.h | 11 +- .../databasecommand_createdynamicplaylist.cpp | 1 + .../databasecommand_deletedynamicplaylist.cpp | 24 +- ... databasecommand_loadallautoplaylists.cpp} | 18 +- ...=> databasecommand_loadallautoplaylists.h} | 22 +- .../databasecommand_loadallstations.cpp | 56 ++++ .../databasecommand_loadallstations.h | 46 ++++ .../databasecommand_renameplaylist.cpp | 11 +- ...basecommand_setdynamicplaylistrevision.cpp | 86 +++--- .../playlist/dynamic/DynamicPlaylist.cpp | 15 +- .../playlist/dynamic/DynamicPlaylist.h | 2 + src/sourcetree/sourcesmodel.cpp | 6 +- src/sourcetree/sourcesmodel.h | 2 +- src/sourcetree/sourcetreeitem.cpp | 252 ++++++++++++++++-- src/sourcetree/sourcetreeitem.h | 33 ++- src/sourcetree/sourcetreeview.cpp | 83 +----- src/sourcetree/sourcetreeview.h | 8 - src/tomahawkwindow.cpp | 4 +- 22 files changed, 647 insertions(+), 241 deletions(-) rename src/libtomahawk/database/{databasecommand_loadalldynamicplaylists.cpp => databasecommand_loadallautoplaylists.cpp} (81%) rename src/libtomahawk/database/{databasecommand_loadalldynamicplaylists.h => databasecommand_loadallautoplaylists.h} (68%) create mode 100644 src/libtomahawk/database/databasecommand_loadallstations.cpp create mode 100644 src/libtomahawk/database/databasecommand_loadallstations.h diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index ca48502c7..d778e762c 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -73,7 +73,8 @@ set( libSources database/databasecommand_setdynamicplaylistrevision.cpp database/databasecommand_createdynamicplaylist.cpp database/databasecommand_loaddynamicplaylist.cpp - database/databasecommand_loadalldynamicplaylists.cpp + database/databasecommand_loadallautoplaylists.cpp + database/databasecommand_loadallstations.cpp database/databasecommand_deletedynamicplaylist.cpp database/databasecommand_addclientauth.cpp database/databasecommand_clientauthvalid.cpp @@ -233,7 +234,8 @@ set( libHeaders database/databasecommand_createdynamicplaylist.h database/databasecommand_loaddynamicplaylist.h database/databasecommand_deletedynamicplaylist.h - database/databasecommand_loadalldynamicplaylists.h + database/databasecommand_loadallautoplaylists.h + database/databasecommand_loadallstations.h database/databasecommand_addclientauth.h database/databasecommand_clientauthvalid.h diff --git a/src/libtomahawk/collection.cpp b/src/libtomahawk/collection.cpp index d9f265d12..b22e1b105 100644 --- a/src/libtomahawk/collection.cpp +++ b/src/libtomahawk/collection.cpp @@ -64,6 +64,7 @@ Collection::addPlaylist( const Tomahawk::playlist_ptr& p ) qDebug() << Q_FUNC_INFO; QList toadd; toadd << p; + qDebug() << "Inserted playlist with guid:" << p->guid(); m_playlists.insert( p->guid(), p ); qDebug() << Q_FUNC_INFO << "Collection name" << name() @@ -74,19 +75,36 @@ Collection::addPlaylist( const Tomahawk::playlist_ptr& p ) void -Collection::addDynamicPlaylist( const Tomahawk::dynplaylist_ptr& p ) +Collection::addAutoPlaylist( const Tomahawk::dynplaylist_ptr& p ) { qDebug() << Q_FUNC_INFO; QList toadd; toadd << p; - m_dynplaylists.insert( p->guid(), p ); + qDebug() << "Inserted dynamic playlist with guid:" << p->guid(); + m_autoplaylists.insert( p->guid(), p ); qDebug() << Q_FUNC_INFO << "Collection name" << name() << "from source id" << source()->id() << "numplaylists:" << m_playlists.count(); - emit dynamicPlaylistsAdded( toadd ); + emit autoPlaylistsAdded( toadd ); } +void +Collection::addStation( const dynplaylist_ptr& s ) +{ + qDebug() << Q_FUNC_INFO; + QList toadd; + toadd << s; + qDebug() << "Inserted station with guid:" << s->guid(); + m_stations.insert( s->guid(), s ); + + qDebug() << Q_FUNC_INFO << "Collection name" << name() + << "from source id" << source()->id() + << "numplaylists:" << m_playlists.count(); + emit stationsAdded( toadd ); +} + + void Collection::deletePlaylist( const Tomahawk::playlist_ptr& p ) @@ -104,32 +122,55 @@ Collection::deletePlaylist( const Tomahawk::playlist_ptr& p ) void -Collection::deleteDynamicPlaylist( const Tomahawk::dynplaylist_ptr& p ) +Collection::deleteAutoPlaylist( const Tomahawk::dynplaylist_ptr& p ) { qDebug() << Q_FUNC_INFO; QList todelete; todelete << p; - m_dynplaylists.remove( p->guid() ); + m_autoplaylists.remove( p->guid() ); qDebug() << Q_FUNC_INFO << "Collection name" << name() << "from source id" << source()->id() << "numplaylists:" << m_playlists.count(); - emit dynamicPlaylistsDeleted( todelete ); + emit autoPlaylistsDeleted( todelete ); +} + +void +Collection::deleteStation( const dynplaylist_ptr& s ) +{ + qDebug() << Q_FUNC_INFO; + QList todelete; + todelete << s; + m_stations.remove( s->guid() ); + + qDebug() << Q_FUNC_INFO << "Collection name" << name() + << "from source id" << source()->id() + << "numplaylists:" << m_playlists.count(); + emit stationsDeleted( todelete ); } playlist_ptr Collection::playlist( const QString& guid ) { + qDebug() << "Returning playlist for guid:" << guid << "found?" << m_playlists.contains( guid ); return m_playlists.value( guid, playlist_ptr() ); } dynplaylist_ptr -Collection::dynamicPlaylist( const QString& guid ) +Collection::autoPlaylist( const QString& guid ) +{ + qDebug() << "Returning auto playlist for guid:" << guid << "found?" << m_autoplaylists.contains( guid ); + return m_autoplaylists.value( guid, dynplaylist_ptr() ); +} + +dynplaylist_ptr +Collection::station( const QString& guid ) { - return m_dynplaylists.value( guid, dynplaylist_ptr() ); + qDebug() << "Returning station for guid:" << guid << "found?" << m_stations.contains( guid ); + return m_stations.value( guid, dynplaylist_ptr() ); } @@ -137,23 +178,37 @@ void Collection::setPlaylists( const QList& plists ) { qDebug() << Q_FUNC_INFO << plists.count(); - foreach ( const playlist_ptr& p, plists ) + foreach ( const playlist_ptr& p, plists ) { + qDebug() << "Batch inserting playlist:" << p->guid(); m_playlists.insert( p->guid(), p ); - + } emit playlistsAdded( plists ); } void -Collection::setDynamicPlaylists( const QList< Tomahawk::dynplaylist_ptr >& plists ) +Collection::setAutoPlaylists( const QList< Tomahawk::dynplaylist_ptr >& plists ) { qDebug() << Q_FUNC_INFO << plists.count(); - foreach ( const dynplaylist_ptr& p, plists ) - m_dynplaylists.insert( p->guid(), p ); -// emit dynamicPlaylistsAdded( plists ); + foreach ( const dynplaylist_ptr& p, plists ) { + qDebug() << "Batch inserting dynamic playlist:" << p->guid(); + m_autoplaylists.insert( p->guid(), p ); + } + emit autoPlaylistsAdded( plists ); } +void +Collection::setStations( const QList< dynplaylist_ptr >& stations ) +{ + qDebug() << Q_FUNC_INFO << stations.count(); + + foreach ( const dynplaylist_ptr& s, stations ) { + qDebug() << "Batch inserting station:" << s->guid(); + m_stations.insert( s->guid(), s ); + } + emit autoPlaylistsAdded( stations ); +} void Collection::setTracks( const QList& tracks ) @@ -193,3 +248,18 @@ Collection::delTracks( const QStringList& files ) emit tracksRemoved( tracks ); } + +void +Collection::moveAutoToStation( const QString& guid ) +{ + + if( m_autoplaylists.contains( guid ) ) + m_stations.insert( guid, m_autoplaylists.take( guid ) ); +} + +void +Collection::moveStationToAuto( const QString& guid ) +{ + if( m_stations.contains( guid ) ) + m_autoplaylists.insert( guid, m_stations.take( guid ) ); +} diff --git a/src/libtomahawk/collection.h b/src/libtomahawk/collection.h index 64f553b6e..fd496cc3a 100644 --- a/src/libtomahawk/collection.h +++ b/src/libtomahawk/collection.h @@ -57,19 +57,25 @@ public: virtual void loadPlaylists() { qDebug() << Q_FUNC_INFO; } virtual void loadTracks() { qDebug() << Q_FUNC_INFO; } - virtual void loadDynamicPlaylists() { qDebug() << Q_FUNC_INFO ; } + virtual void loadAutoPlaylists() { qDebug() << Q_FUNC_INFO ; } + virtual void loadStations() { qDebug() << Q_FUNC_INFO ; } virtual Tomahawk::playlist_ptr playlist( const QString& guid ); - virtual Tomahawk::dynplaylist_ptr dynamicPlaylist( const QString& guid ); + virtual Tomahawk::dynplaylist_ptr autoPlaylist( const QString& guid ); + virtual Tomahawk::dynplaylist_ptr station( const QString& guid ); virtual void addPlaylist( const Tomahawk::playlist_ptr& p ); virtual void deletePlaylist( const Tomahawk::playlist_ptr& p ); - virtual void addDynamicPlaylist( const Tomahawk::dynplaylist_ptr& p ); - virtual void deleteDynamicPlaylist( const Tomahawk::dynplaylist_ptr& p ); + virtual void addAutoPlaylist( const Tomahawk::dynplaylist_ptr& p ); + virtual void deleteAutoPlaylist( const Tomahawk::dynplaylist_ptr& p ); + + virtual void addStation( const Tomahawk::dynplaylist_ptr& s ); + virtual void deleteStation( const Tomahawk::dynplaylist_ptr& s ); virtual QList< Tomahawk::playlist_ptr > playlists() { return m_playlists.values(); } - virtual QList< Tomahawk::dynplaylist_ptr > dynamicPlaylists() { return m_dynplaylists.values(); } + virtual QList< Tomahawk::dynplaylist_ptr > autoPlaylists() { return m_autoplaylists.values(); } + virtual QList< Tomahawk::dynplaylist_ptr > stations() { return m_stations.values(); } virtual QList< Tomahawk::query_ptr > tracks() { return m_tracks; } const source_ptr& source() const; @@ -82,17 +88,19 @@ signals: void playlistsAdded( const QList& ); void playlistsDeleted( const QList& ); - void dynamicPlaylistsAdded( const QList& ); - void dynamicPlaylistsDeleted( const QList& ); -// void stationsAdded( const QList& ); -// void stationsDeleted( const QList& ); + void autoPlaylistsAdded( const QList& ); + void autoPlaylistsDeleted( const QList& ); + + void stationsAdded( const QList& ); + void stationsDeleted( const QList& ); public slots: virtual void addTracks( const QList& newitems ) = 0; virtual void removeTracks( const QDir& dir ) = 0; void setPlaylists( const QList& plists ); - void setDynamicPlaylists( const QList< Tomahawk::dynplaylist_ptr >& dynplists ); + void setAutoPlaylists( const QList< Tomahawk::dynplaylist_ptr >& autoplists ); + void setStations( const QList< Tomahawk::dynplaylist_ptr >& stations ); void setTracks( const QList& tracks ); void delTracks( const QStringList& files ); @@ -108,7 +116,13 @@ private: source_ptr m_source; QList< Tomahawk::query_ptr > m_tracks; QHash< QString, Tomahawk::playlist_ptr > m_playlists; - QHash< QString, Tomahawk::dynplaylist_ptr > m_dynplaylists; + QHash< QString, Tomahawk::dynplaylist_ptr > m_autoplaylists; + QHash< QString, Tomahawk::dynplaylist_ptr > m_stations; + + // HACK see line 99 in the dbcmd for why we need this for backwards-compatibility + void moveAutoToStation( const QString& guid ); + void moveStationToAuto( const QString& guid ); + friend class ::DatabaseCommand_SetDynamicPlaylistRevision; }; }; // ns diff --git a/src/libtomahawk/database/databasecollection.cpp b/src/libtomahawk/database/databasecollection.cpp index 0348cd5e6..45537610d 100644 --- a/src/libtomahawk/database/databasecollection.cpp +++ b/src/libtomahawk/database/databasecollection.cpp @@ -23,7 +23,8 @@ #include "databasecommand_addfiles.h" #include "databasecommand_deletefiles.h" #include "databasecommand_loadallplaylists.h" -#include "databasecommand_loadalldynamicplaylists.h" +#include "databasecommand_loadallautoplaylists.h" +#include "databasecommand_loadallstations.h" using namespace Tomahawk; @@ -48,21 +49,28 @@ DatabaseCollection::loadPlaylists() void -DatabaseCollection::loadDynamicPlaylists() +DatabaseCollection::loadAutoPlaylists() { qDebug() << Q_FUNC_INFO; - DatabaseCommand_LoadAllDynamicPlaylists* cmd = new DatabaseCommand_LoadAllDynamicPlaylists( source() ); + DatabaseCommand_LoadAllAutoPlaylists* cmd = new DatabaseCommand_LoadAllAutoPlaylists( source() ); - connect( cmd, SIGNAL( dynamicPlaylistLoaded( Tomahawk::source_ptr, QVariantList ) ), - SLOT( dynamicPlaylistCreated( const Tomahawk::source_ptr&, const QVariantList& ) ) );/* connect( cmd, SIGNAL( autoPlaylistLoaded( Tomahawk::source_ptr, QVariantList ) ), - SLOT( dynamicPlaylistCreated( const Tomahawk::source_ptr&, const QVariantList& ) ) ); - connect( cmd, SIGNAL( stationLoaded( Tomahawk::source_ptr, QVariantList ) ), - SLOT( dynamicPlaylistCreated( const Tomahawk::source_ptr&, const QVariantList& ) ) );*/ + SLOT( autoPlaylistCreated( const Tomahawk::source_ptr&, const QVariantList& ) ) ); Database::instance()->enqueue( QSharedPointer( cmd ) ); } +void +DatabaseCollection::loadStations() +{ + qDebug() << Q_FUNC_INFO; + DatabaseCommand_LoadAllStations* cmd = new DatabaseCommand_LoadAllStations( source() ); + + connect( cmd, SIGNAL( stationLoaded( Tomahawk::source_ptr, QVariantList ) ), + SLOT( stationCreated( const Tomahawk::source_ptr&, const QVariantList& ) ) ); + + Database::instance()->enqueue( QSharedPointer( cmd ) );} + void DatabaseCollection::loadTracks() @@ -113,16 +121,30 @@ DatabaseCollection::playlists() } -QList< dynplaylist_ptr > DatabaseCollection::dynamicPlaylists() +QList< dynplaylist_ptr > +DatabaseCollection::autoPlaylists() { qDebug() << Q_FUNC_INFO; - if ( Collection::dynamicPlaylists().isEmpty() ) + if ( Collection::autoPlaylists().isEmpty() ) { - loadDynamicPlaylists(); + loadAutoPlaylists(); } - return Collection::dynamicPlaylists(); + return Collection::autoPlaylists(); +} + +QList< dynplaylist_ptr > +DatabaseCollection::stations() +{ + qDebug() << Q_FUNC_INFO; + + if ( Collection::stations().isEmpty() ) + { + loadStations(); + } + + return Collection::stations(); } @@ -139,8 +161,7 @@ DatabaseCollection::tracks() return Collection::tracks(); } - -void DatabaseCollection::dynamicPlaylistCreated( const source_ptr& source, const QVariantList& data ) +void DatabaseCollection::autoPlaylistCreated( const source_ptr& source, const QVariantList& data ) { dynplaylist_ptr p( new DynamicPlaylist( source, //src data[0].toString(), //current rev @@ -153,6 +174,23 @@ void DatabaseCollection::dynamicPlaylistCreated( const source_ptr& source, const data[7].toBool(), //shared data[8].toInt(), //lastmod data[9].toString() ) ); //GUID - addDynamicPlaylist( p ); + addAutoPlaylist( p ); } +void DatabaseCollection::stationCreated( const source_ptr& source, const QVariantList& data ) +{ + dynplaylist_ptr p( new DynamicPlaylist( source, //src + data[0].toString(), //current rev + data[1].toString(), //title + data[2].toString(), //info + data[3].toString(), //creator + data[4].toUInt(), // createdOn + data[5].toString(), // dynamic type + static_cast(data[6].toInt()), // dynamic mode + data[7].toBool(), //shared + data[8].toInt(), //lastmod + data[9].toString() ) ); //GUID + addStation( p ); +} + + diff --git a/src/libtomahawk/database/databasecollection.h b/src/libtomahawk/database/databasecollection.h index 5b15913c0..d20480d6d 100644 --- a/src/libtomahawk/database/databasecollection.h +++ b/src/libtomahawk/database/databasecollection.h @@ -1,5 +1,5 @@ /* === This file is part of Tomahawk Player - === - * + * * Copyright 2010-2011, Christian Muehlhaeuser * * Tomahawk is free software: you can redistribute it and/or modify @@ -40,18 +40,21 @@ public: virtual void loadTracks(); virtual void loadPlaylists(); - virtual void loadDynamicPlaylists(); + virtual void loadAutoPlaylists(); + virtual void loadStations(); virtual QList< Tomahawk::playlist_ptr > playlists(); virtual QList< Tomahawk::query_ptr > tracks(); - virtual QList< Tomahawk::dynplaylist_ptr > dynamicPlaylists(); + virtual QList< Tomahawk::dynplaylist_ptr > autoPlaylists(); + virtual QList< Tomahawk::dynplaylist_ptr > stations(); public slots: virtual void addTracks( const QList& newitems ); virtual void removeTracks( const QDir& dir ); private slots: - void dynamicPlaylistCreated( const Tomahawk::source_ptr& source, const QVariantList& data ); + void stationCreated( const Tomahawk::source_ptr& source, const QVariantList& data ); + void autoPlaylistCreated( const Tomahawk::source_ptr& source, const QVariantList& data ); }; #endif // DATABASECOLLECTION_H diff --git a/src/libtomahawk/database/databasecommand_createdynamicplaylist.cpp b/src/libtomahawk/database/databasecommand_createdynamicplaylist.cpp index b0aa81b3b..597f0c07d 100644 --- a/src/libtomahawk/database/databasecommand_createdynamicplaylist.cpp +++ b/src/libtomahawk/database/databasecommand_createdynamicplaylist.cpp @@ -57,6 +57,7 @@ DatabaseCommand_CreateDynamicPlaylist::exec( DatabaseImpl* lib ) DatabaseCommand_CreatePlaylist::createPlaylist( lib, true ); qDebug() << "Created normal playlist, now creating additional dynamic info!"; + qDebug() << "Create dynamic execing!" << m_playlist << m_v; TomahawkSqlQuery cre = lib->newquery(); cre.prepare( "INSERT INTO dynamic_playlist( guid, pltype, plmode ) " diff --git a/src/libtomahawk/database/databasecommand_deletedynamicplaylist.cpp b/src/libtomahawk/database/databasecommand_deletedynamicplaylist.cpp index 34c5defbd..718fcfc03 100644 --- a/src/libtomahawk/database/databasecommand_deletedynamicplaylist.cpp +++ b/src/libtomahawk/database/databasecommand_deletedynamicplaylist.cpp @@ -1,5 +1,5 @@ /* === This file is part of Tomahawk Player - === - * + * * Copyright 2010-2011, Christian Muehlhaeuser * * Tomahawk is free software: you can redistribute it and/or modify @@ -18,9 +18,11 @@ #include "databasecommand_deletedynamicplaylist.h" -#include +#include "dynamic/DynamicPlaylist.h" #include "network/servent.h" - + +#include + using namespace Tomahawk; @@ -37,10 +39,10 @@ DatabaseCommand_DeleteDynamicPlaylist::exec( DatabaseImpl* lib ) qDebug() << "deleting dynamic playlist:" << m_playlistguid; DatabaseCommand_DeletePlaylist::exec( lib ); TomahawkSqlQuery cre = lib->newquery(); - + cre.prepare( "DELETE FROM dynamic_playlist WHERE guid = :id" ); cre.bindValue( ":id", m_playlistguid ); - + cre.exec(); } @@ -54,12 +56,16 @@ DatabaseCommand_DeleteDynamicPlaylist::postCommitHook() qDebug() << "Source has gone offline, not emitting to GUI."; return; } - - dynplaylist_ptr playlist = source()->collection()->dynamicPlaylist( m_playlistguid ); + // we arent sure which it is, but it can't be more th an one. so try both + dynplaylist_ptr playlist = source()->collection()->autoPlaylist( m_playlistguid ); + if( playlist.isNull() ) + playlist = source()->collection()->station( m_playlistguid ); + + qDebug() << "Just tried to load playlist for deletion:" << m_playlistguid << "Did we get a null one?" << playlist.isNull() << "is it a station?" << (playlist->mode() == OnDemand); Q_ASSERT( !playlist.isNull() ); - + playlist->reportDeleted( playlist ); - + if( source()->isLocal() ) Servent::instance()->triggerDBSync(); } diff --git a/src/libtomahawk/database/databasecommand_loadalldynamicplaylists.cpp b/src/libtomahawk/database/databasecommand_loadallautoplaylists.cpp similarity index 81% rename from src/libtomahawk/database/databasecommand_loadalldynamicplaylists.cpp rename to src/libtomahawk/database/databasecommand_loadallautoplaylists.cpp index b85c19dba..7278db812 100644 --- a/src/libtomahawk/database/databasecommand_loadalldynamicplaylists.cpp +++ b/src/libtomahawk/database/databasecommand_loadallautoplaylists.cpp @@ -16,7 +16,7 @@ * along with Tomahawk. If not, see . */ -#include "databasecommand_loadalldynamicplaylists.h" +#include "databasecommand_loadallautoplaylists.h" #include @@ -26,15 +26,14 @@ using namespace Tomahawk; -void DatabaseCommand_LoadAllDynamicPlaylists::exec( DatabaseImpl* dbi ) +void DatabaseCommand_LoadAllAutoPlaylists::exec( DatabaseImpl* dbi ) { TomahawkSqlQuery query = dbi->newquery(); query.exec( QString( "SELECT playlist.guid as guid, title, info, creator, createdOn, lastmodified, shared, currentrevision, dynamic_playlist.pltype, dynamic_playlist.plmode " - "FROM playlist, dynamic_playlist WHERE source %1 AND dynplaylist = 'true' AND playlist.guid = dynamic_playlist.guid" ) - .arg( source()->isLocal() ? "IS NULL" : - QString( "=%1" ).arg( source()->id() ) - ) ); + "FROM playlist, dynamic_playlist WHERE source %1 AND dynplaylist = 'true' AND playlist.guid = dynamic_playlist.guid AND dynamic_playlist.plmode = %2" ) + .arg( source()->isLocal() ? "IS NULL" : QString( "=%1" ).arg( source()->id() ) ) + .arg( Static ) ); QList plists; while ( query.next() ) @@ -49,12 +48,7 @@ void DatabaseCommand_LoadAllDynamicPlaylists::exec( DatabaseImpl* dbi ) << query.value(6).toBool() //shared << query.value(5).toInt() //lastmod << query.value(0).toString(); //GUID - emit dynamicPlaylistLoaded( source(), data ); - /* - if( static_cast( query.value(8).toInt() ) == Static ) - emit autoPlaylistLoaded( source(), data ); - else - emit stationLoaded( source(), data );*/ + emit autoPlaylistLoaded( source(), data ); } emit done(); diff --git a/src/libtomahawk/database/databasecommand_loadalldynamicplaylists.h b/src/libtomahawk/database/databasecommand_loadallautoplaylists.h similarity index 68% rename from src/libtomahawk/database/databasecommand_loadalldynamicplaylists.h rename to src/libtomahawk/database/databasecommand_loadallautoplaylists.h index eb56239a9..6352ff360 100644 --- a/src/libtomahawk/database/databasecommand_loadalldynamicplaylists.h +++ b/src/libtomahawk/database/databasecommand_loadallautoplaylists.h @@ -1,5 +1,5 @@ /* === This file is part of Tomahawk Player - === - * + * * Copyright 2010-2011, Christian Muehlhaeuser * * Tomahawk is free software: you can redistribute it and/or modify @@ -16,8 +16,8 @@ * along with Tomahawk. If not, see . */ -#ifndef DATABASECOMMAND_LOADALLDYNAMICPLAYLISTS_H -#define DATABASECOMMAND_LOADALLDYNAMICPLAYLISTS_H +#ifndef DATABASECOMMAND_LOADALLAUTOPLAYLISTS_H +#define DATABASECOMMAND_LOADALLAUTOPLAYLISTS_H #include #include @@ -25,22 +25,22 @@ #include "databasecommand.h" #include "typedefs.h" -class DatabaseCommand_LoadAllDynamicPlaylists : public DatabaseCommand +class DatabaseCommand_LoadAllAutoPlaylists : public DatabaseCommand { Q_OBJECT - + public: - explicit DatabaseCommand_LoadAllDynamicPlaylists( const Tomahawk::source_ptr& s, QObject* parent = 0 ) + explicit DatabaseCommand_LoadAllAutoPlaylists( const Tomahawk::source_ptr& s, QObject* parent = 0 ) : DatabaseCommand( s, parent ) {} - + virtual void exec( DatabaseImpl* ); virtual bool doesMutates() const { return false; } - virtual QString commandname() const { return "loadalldynamicplaylists"; } - + virtual QString commandname() const { return "loadallautoplaylists"; } + signals: - void dynamicPlaylistLoaded( const Tomahawk::source_ptr& source, const QVariantList& data ); + void autoPlaylistLoaded( const Tomahawk::source_ptr& source, const QVariantList& data ); void done(); }; -#endif // DATABASECOMMAND_ADDFILES_H +#endif diff --git a/src/libtomahawk/database/databasecommand_loadallstations.cpp b/src/libtomahawk/database/databasecommand_loadallstations.cpp new file mode 100644 index 000000000..9f75c7f2e --- /dev/null +++ b/src/libtomahawk/database/databasecommand_loadallstations.cpp @@ -0,0 +1,56 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Christian Muehlhaeuser + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#include "databasecommand_loadallstations.h" + +#include + +#include "dynamic/DynamicPlaylist.h" +#include "databaseimpl.h" + +using namespace Tomahawk; + + +void DatabaseCommand_LoadAllStations::exec( DatabaseImpl* dbi ) +{ + TomahawkSqlQuery query = dbi->newquery(); + + query.exec( QString( "SELECT playlist.guid as guid, title, info, creator, createdOn, lastmodified, shared, currentrevision, dynamic_playlist.pltype, dynamic_playlist.plmode " + "FROM playlist, dynamic_playlist WHERE source %1 AND dynplaylist = 'true' AND playlist.guid = dynamic_playlist.guid AND dynamic_playlist.plmode = %2" ) + .arg( source()->isLocal() ? "IS NULL" : QString( "=%1" ).arg( source()->id() ) ) + .arg( OnDemand ) ); + + QList plists; + while ( query.next() ) + { + QVariantList data = QVariantList() << query.value(7).toString() //current rev + << query.value(1).toString() //title + << query.value(2).toString() //info + << query.value(3).toString() //creator + << query.value(4).toString() //createdOn + << query.value(8).toString() // dynamic type + << static_cast(query.value(9).toInt()) // dynamic mode + << query.value(6).toBool() //shared + << query.value(5).toInt() //lastmod + << query.value(0).toString(); //GUID + emit stationLoaded( source(), data ); + } + + emit done(); +} + diff --git a/src/libtomahawk/database/databasecommand_loadallstations.h b/src/libtomahawk/database/databasecommand_loadallstations.h new file mode 100644 index 000000000..4cb29dc2a --- /dev/null +++ b/src/libtomahawk/database/databasecommand_loadallstations.h @@ -0,0 +1,46 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Christian Muehlhaeuser + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#ifndef DATABASECOMMAND_LOADALLSTATIONS_H +#define DATABASECOMMAND_LOADALLSTATIONS_H + +#include +#include + +#include "databasecommand.h" +#include "typedefs.h" + +class DatabaseCommand_LoadAllStations : public DatabaseCommand +{ + Q_OBJECT + +public: + explicit DatabaseCommand_LoadAllStations( const Tomahawk::source_ptr& s, QObject* parent = 0 ) + : DatabaseCommand( s, parent ) + {} + + virtual void exec( DatabaseImpl* ); + virtual bool doesMutates() const { return false; } + virtual QString commandname() const { return "loadallstations"; } + +signals: + void stationLoaded( const Tomahawk::source_ptr& source, const QVariantList& data ); + void done(); +}; + +#endif \ No newline at end of file diff --git a/src/libtomahawk/database/databasecommand_renameplaylist.cpp b/src/libtomahawk/database/databasecommand_renameplaylist.cpp index 4187ae27e..2912068f8 100644 --- a/src/libtomahawk/database/databasecommand_renameplaylist.cpp +++ b/src/libtomahawk/database/databasecommand_renameplaylist.cpp @@ -1,5 +1,5 @@ /* === This file is part of Tomahawk Player - === - * + * * Copyright 2010-2011, Christian Muehlhaeuser * * Tomahawk is free software: you can redistribute it and/or modify @@ -21,6 +21,7 @@ #include #include "network/servent.h" +#include "collection.h" using namespace Tomahawk; @@ -62,8 +63,14 @@ DatabaseCommand_RenamePlaylist::postCommitHook() qDebug() << "Source has gone offline, not emitting to GUI."; return; } - + playlist_ptr playlist = source()->collection()->playlist( m_playlistguid ); + // fallback, check for auto and stations too + if( playlist.isNull() ) + playlist = source()->collection()->autoPlaylist( m_playlistguid ); + if( playlist.isNull() ) + playlist = source()->collection()->station( m_playlistguid ); + Q_ASSERT( !playlist.isNull() ); qDebug() << "Renaming old playlist" << playlist->title() << "to" << m_playlistTitle << m_playlistguid; diff --git a/src/libtomahawk/database/databasecommand_setdynamicplaylistrevision.cpp b/src/libtomahawk/database/databasecommand_setdynamicplaylistrevision.cpp index 39494f3fd..728af40a9 100644 --- a/src/libtomahawk/database/databasecommand_setdynamicplaylistrevision.cpp +++ b/src/libtomahawk/database/databasecommand_setdynamicplaylistrevision.cpp @@ -1,5 +1,5 @@ /* === This file is part of Tomahawk Player - === - * + * * Copyright 2010-2011, Christian Muehlhaeuser * * Tomahawk is free software: you can redistribute it and/or modify @@ -24,15 +24,15 @@ #include "dynamic/DynamicPlaylist.h" #include "dynamic/DynamicControl.h" -DatabaseCommand_SetDynamicPlaylistRevision::DatabaseCommand_SetDynamicPlaylistRevision(const Tomahawk::source_ptr& s, - const QString& playlistguid, - const QString& newrev, - const QString& oldrev, - const QStringList& orderedguids, - const QList< plentry_ptr >& addedentries, +DatabaseCommand_SetDynamicPlaylistRevision::DatabaseCommand_SetDynamicPlaylistRevision(const Tomahawk::source_ptr& s, + const QString& playlistguid, + const QString& newrev, + const QString& oldrev, + const QStringList& orderedguids, + const QList< plentry_ptr >& addedentries, const QList& entries, - const QString& type, - GeneratorMode mode, + const QString& type, + GeneratorMode mode, const QList< dyncontrol_ptr >& controls ) : DatabaseCommand_SetPlaylistRevision( s, playlistguid, newrev, oldrev, orderedguids, addedentries, entries ) , m_type( type ) @@ -42,12 +42,12 @@ DatabaseCommand_SetDynamicPlaylistRevision::DatabaseCommand_SetDynamicPlaylistRe } -DatabaseCommand_SetDynamicPlaylistRevision::DatabaseCommand_SetDynamicPlaylistRevision(const Tomahawk::source_ptr& s, - const QString& playlistguid, - const QString& newrev, - const QString& oldrev, - const QString& type, - GeneratorMode mode, +DatabaseCommand_SetDynamicPlaylistRevision::DatabaseCommand_SetDynamicPlaylistRevision(const Tomahawk::source_ptr& s, + const QString& playlistguid, + const QString& newrev, + const QString& oldrev, + const QString& type, + GeneratorMode mode, const QList< dyncontrol_ptr >& controls ) : DatabaseCommand_SetPlaylistRevision( s, playlistguid, newrev, oldrev, QStringList(), QList< plentry_ptr >(), QList< plentry_ptr >() ) , m_type( type ) @@ -61,16 +61,16 @@ QVariantList DatabaseCommand_SetDynamicPlaylistRevision::controlsV() { if( m_controls.isEmpty() ) return m_controlsV; - + if( !m_controls.isEmpty() && m_controlsV.isEmpty() ) { - foreach( const dyncontrol_ptr& control, m_controls ) + foreach( const dyncontrol_ptr& control, m_controls ) { m_controlsV << QJson::QObjectHelper::qobject2qvariant( control.data() ); } } return m_controlsV; - + } void @@ -82,20 +82,32 @@ DatabaseCommand_SetDynamicPlaylistRevision::postCommitHook() qDebug() << "Source has gone offline, not emitting to GUI."; return; } - + QStringList orderedentriesguids; foreach( const QVariant& v, orderedguids() ) orderedentriesguids << v.toString(); - + Q_ASSERT( !source().isNull() ); Q_ASSERT( !source()->collection().isNull() ); qDebug() << "Postcommitting this playlist:" << playlistguid() << source().isNull() << source().data(); + // private, but we are a friend. will recall itself in its own thread: - dynplaylist_ptr playlist = source()->collection()->dynamicPlaylist( playlistguid() ); - + dynplaylist_ptr playlist = source()->collection()->autoPlaylist( playlistguid() ); + if( playlist.isNull() ) + playlist = source()->collection()->station( playlistguid() ); + + // workaround a bug in pre-0.1.0 tomahawks. they created dynamic playlists in OnDemand mode *always*, and then set the mode to the real one. + // now that we separate them, if we get them as one and then get a changed mode, the playlist ends up in the wrong bucket in Collection. + // so here we fix it if we have to. + // HACK + qDebug() << "Does this need FIXING?" << playlist->mode() << source()->collection()->autoPlaylist( playlistguid() ).isNull() << source()->collection()->station( playlistguid() ).isNull(); + if( playlist->mode() == Static && source()->collection()->autoPlaylist( playlistguid() ).isNull() ) // should be here + source()->collection()->moveStationToAuto( playlistguid() ); + else if( playlist->mode() == OnDemand && source()->collection()->station( playlistguid() ).isNull() ) // should be here + source()->collection()->moveAutoToStation( playlistguid() ); if ( playlist.isNull() ) { - qDebug() <<"Got null playlist with guid:" << playlistguid() << "from source and collection:" << source()->friendlyName() << source()->collection()->name(); + qDebug() <<"Got null playlist with guid:" << playlistguid() << "from source and collection:" << source()->friendlyName() << source()->collection()->name() << "and mode is static?:" << (m_mode == Static); Q_ASSERT( !playlist.isNull() ); return; } @@ -103,7 +115,7 @@ DatabaseCommand_SetDynamicPlaylistRevision::postCommitHook() QList controlMap; foreach( const QVariant& v, m_controlsV ) controlMap << v.toMap(); - + if( m_mode == OnDemand ) playlist->setRevision( newrev(), true, // this *is* the newest revision so far @@ -145,7 +157,7 @@ void DatabaseCommand_SetDynamicPlaylistRevision::exec( DatabaseImpl* lib ) { DatabaseCommand_SetPlaylistRevision::exec( lib ); - + QVariantList newcontrols; if( m_controlsV.isEmpty() && !m_controls.isEmpty() ) { foreach( const dyncontrol_ptr& control, m_controls ) { @@ -156,21 +168,21 @@ DatabaseCommand_SetDynamicPlaylistRevision::exec( DatabaseImpl* lib ) newcontrols << v.toMap().value( "id" ); } } - + QJson::Serializer ser; const QByteArray newcontrols_data = ser.serialize( newcontrols ); - + TomahawkSqlQuery query = lib->newquery(); QString sql = "INSERT INTO dynamic_playlist_revision (guid, controls, plmode, pltype) " "VALUES(?, ?, ?, ?)"; - + query.prepare( sql ); query.addBindValue( m_newrev ); query.addBindValue( newcontrols_data ); query.addBindValue( QString::number( (int) m_mode ) ); query.addBindValue( m_type ); query.exec(); - + // delete all the old controls, replace with new onws qDebug() << "Deleting controls with playlist id" << m_playlistguid; TomahawkSqlQuery delQuery = lib->newquery(); @@ -178,7 +190,7 @@ DatabaseCommand_SetDynamicPlaylistRevision::exec( DatabaseImpl* lib ) delQuery.addBindValue( m_playlistguid ); if( !delQuery.exec() ) qWarning() << "Failed to delete controls from dynamic playlist controls table"; - + TomahawkSqlQuery controlsQuery = lib->newquery(); controlsQuery.prepare( "INSERT INTO dynamic_playlist_controls( id, playlist, selectedType, match, input ) " "VALUES( ?, ?, ?, ?, ? )" ); @@ -191,7 +203,7 @@ DatabaseCommand_SetDynamicPlaylistRevision::exec( DatabaseImpl* lib ) controlsQuery.addBindValue( control->selectedType() ); controlsQuery.addBindValue( control->match() ); controlsQuery.addBindValue( control->input() ); - + controlsQuery.exec(); } } else { @@ -203,23 +215,23 @@ DatabaseCommand_SetDynamicPlaylistRevision::exec( DatabaseImpl* lib ) controlsQuery.addBindValue( control.value( "selectedType" ) ); controlsQuery.addBindValue( control.value( "match" ) ); controlsQuery.addBindValue( control.value( "input" ) ); - + controlsQuery.exec(); } - + } if( m_applied ) { qDebug() << "updating dynamic playlist, optimistic locking okay"; - + TomahawkSqlQuery query2 = lib->newquery(); query2.prepare( "UPDATE dynamic_playlist SET pltype = ?, plmode = ? WHERE guid = ?" ); query2.bindValue( 0, m_type ); query2.bindValue( 1, m_mode ); query2.bindValue( 2, m_playlistguid ); query2.exec(); - + } - - + + } diff --git a/src/libtomahawk/playlist/dynamic/DynamicPlaylist.cpp b/src/libtomahawk/playlist/dynamic/DynamicPlaylist.cpp index d81c27324..5122f8260 100644 --- a/src/libtomahawk/playlist/dynamic/DynamicPlaylist.cpp +++ b/src/libtomahawk/playlist/dynamic/DynamicPlaylist.cpp @@ -70,11 +70,13 @@ DynamicPlaylist::DynamicPlaylist ( const Tomahawk::source_ptr& author, const QString& info, const QString& creator, const QString& type, + GeneratorMode mode, bool shared ) : Playlist ( author, guid, title, info, creator, shared ) { qDebug() << "Creating Dynamic Playlist 2"; m_generator = geninterface_ptr( GeneratorFactory::create( type ) ); + m_generator->setMode( mode ); } geninterface_ptr @@ -115,11 +117,12 @@ DynamicPlaylist::create( const Tomahawk::source_ptr& author, const QString& title, const QString& info, const QString& creator, + GeneratorMode mode, bool shared ) { // default generator QString type = ""; - dynplaylist_ptr dynplaylist = dynplaylist_ptr( new DynamicPlaylist( author, guid, title, info, creator, type, shared ) ); + dynplaylist_ptr dynplaylist = dynplaylist_ptr( new DynamicPlaylist( author, guid, title, info, creator, type, mode, shared ) ); DatabaseCommand_CreateDynamicPlaylist* cmd = new DatabaseCommand_CreateDynamicPlaylist( author, dynplaylist ); connect( cmd, SIGNAL(finished()), dynplaylist.data(), SIGNAL(created()) ); @@ -256,7 +259,10 @@ DynamicPlaylist::reportCreated( const Tomahawk::dynplaylist_ptr& self ) // will emit Collection::playlistCreated(...) // qDebug() << "Creating dynplaylist belonging to:" << author().data() << author().isNull(); // qDebug() << "REPORTING DYNAMIC PLAYLIST CREATED:" << this << author()->friendlyName(); - author()->collection()->addDynamicPlaylist( self ); + if( self->mode() == Static ) + author()->collection()->addAutoPlaylist( self ); + else + author()->collection()->addStation( self ); } void @@ -265,7 +271,10 @@ DynamicPlaylist::reportDeleted( const Tomahawk::dynplaylist_ptr& self ) qDebug() << Q_FUNC_INFO; Q_ASSERT( self.data() == this ); // will emit Collection::playlistDeleted(...) - author()->collection()->deleteDynamicPlaylist( self ); + if( self->mode() == Static ) + author()->collection()->deleteAutoPlaylist( self ); + else + author()->collection()->deleteStation( self ); emit deleted( self ); } diff --git a/src/libtomahawk/playlist/dynamic/DynamicPlaylist.h b/src/libtomahawk/playlist/dynamic/DynamicPlaylist.h index 4312d67b9..7db146fd1 100644 --- a/src/libtomahawk/playlist/dynamic/DynamicPlaylist.h +++ b/src/libtomahawk/playlist/dynamic/DynamicPlaylist.h @@ -81,6 +81,7 @@ public: const QString& title, const QString& info, const QString& creator, + GeneratorMode mode, bool shared ); static bool remove( const dynplaylist_ptr& playlist ); @@ -180,6 +181,7 @@ private: const QString& info, const QString& creator, const QString& type, + GeneratorMode mode, bool shared ); private: diff --git a/src/sourcetree/sourcesmodel.cpp b/src/sourcetree/sourcesmodel.cpp index 6f4f72653..ddd2af04f 100644 --- a/src/sourcetree/sourcesmodel.cpp +++ b/src/sourcetree/sourcesmodel.cpp @@ -377,14 +377,14 @@ SourcesModel::indexFromItem( SourceTreeItem* item ) const curItem = curItem->parent(); } - qDebug() << "build child index list:" << childIndexList; +// qDebug() << "build child index list:" << childIndexList; // now rebuild the qmodelindex we need QModelIndex idx; for( int i = childIndexList.size() - 1; i >= 0 ; i-- ) { idx = index( childIndexList[ i ], 0, idx ); } - qDebug() << "Got index from item:" << idx << idx.data( Qt::DisplayRole ).toString(); - qDebug() << "parent:" << idx.parent(); +// qDebug() << "Got index from item:" << idx << idx.data( Qt::DisplayRole ).toString(); +// qDebug() << "parent:" << idx.parent(); return idx; } diff --git a/src/sourcetree/sourcesmodel.h b/src/sourcetree/sourcesmodel.h index eb3111b8b..accd8c40f 100644 --- a/src/sourcetree/sourcesmodel.h +++ b/src/sourcetree/sourcesmodel.h @@ -48,7 +48,7 @@ public: StaticPlaylist = 3, AutomaticPlaylist = 4, - Stations = 5, + Station = 5, GenericPage = 6 }; diff --git a/src/sourcetree/sourcetreeitem.cpp b/src/sourcetree/sourcetreeitem.cpp index 50c22f2a2..aa6a25e28 100644 --- a/src/sourcetree/sourcetreeitem.cpp +++ b/src/sourcetree/sourcetreeitem.cpp @@ -197,6 +197,111 @@ PlaylistItem::setData(const QVariant& v, bool role) return false; } +DynamicPlaylistItem::DynamicPlaylistItem( SourcesModel* mdl, SourceTreeItem* parent, const dynplaylist_ptr& pl, int index ) + : PlaylistItem( mdl, parent, pl.staticCast< Playlist >(), index ) + , m_dynplaylist( pl ) +{ + setRowType( m_dynplaylist->mode() == Static ? SourcesModel::AutomaticPlaylist : SourcesModel::Station ); + + connect( pl.data(), SIGNAL( dynamicRevisionLoaded( Tomahawk::DynamicPlaylistRevision ) ), + SLOT( onDynamicPlaylistLoaded( Tomahawk::DynamicPlaylistRevision ) ), Qt::QueuedConnection ); + + if( ViewManager::instance()->pageForDynPlaylist( pl ) ) + model()->linkSourceItemToPage( this, ViewManager::instance()->pageForDynPlaylist( pl ) ); +} + +DynamicPlaylistItem::~DynamicPlaylistItem() +{ +} + +void +DynamicPlaylistItem::activate() +{ + ViewPage* p = ViewManager::instance()->show( m_dynplaylist ); + model()->linkSourceItemToPage( this, p ); +} + +void +DynamicPlaylistItem::onDynamicPlaylistLoaded( DynamicPlaylistRevision revision ) +{ + setLoaded( true ); + checkReparentHackNeeded( revision ); + // END HACK + emit updated(); +} + +void +DynamicPlaylistItem::checkReparentHackNeeded( const DynamicPlaylistRevision& revision ) +{ + // HACK HACK HACK workaround for an ugly hack where we have to be compatible with older tomahawks (pre-0.1.0) that created dynplaylists as OnDemand then changed them to Static if they were static. + // we need to reparent this playlist to the correct category :-/. + CategoryItem* cat = qobject_cast< CategoryItem* >( parent() ); + qDebug() << "with category" << cat; + if( cat ) qDebug() << "and cat type:" << cat->categoryType(); + if( cat ) { + CategoryItem* from = cat; + CategoryItem* to = 0; + if( cat->categoryType() == SourcesModel::PlaylistsCategory && revision.mode == OnDemand ) { // WRONG + CollectionItem* col = qobject_cast< CollectionItem* >( cat->parent() ); + to = col->stationsCategory(); + if( !to ) { // you have got to be fucking kidding me + int fme = col->children().count(); + col->beginRowsAdded( fme, fme ); + to = new CategoryItem( model(), col, SourcesModel::StationsCategory, false ); + col->appendChild( to ); // we f'ing know it's not local b/c we're not getting into this mess ourselves + col->endRowsAdded(); + col->setStationsCategory( to ); + } + } else if( cat->categoryType() == SourcesModel::StationsCategory && revision.mode == Static ) { // WRONG + CollectionItem* col = qobject_cast< CollectionItem* >( cat->parent() ); + to = col->playlistsCategory(); + qDebug() << "TRYING TO HACK TO:" << to; + if( !to ) { // you have got to be fucking kidding me + int fme = col->children().count(); + col->beginRowsAdded( fme, fme ); + to = new CategoryItem( model(), col, SourcesModel::PlaylistsCategory, false ); + col->appendChild( to ); // we f'ing know it's not local b/c we're not getting into this mess ourselves + col->endRowsAdded(); + col->setPlaylistsCategory( to ); + } + } + if( to ) { + qDebug() << "HACKING! moving dynamic playlist from" << from->text() << "to:" << to->text(); + // remove and add + int idx = from->children().indexOf( this ); + from->beginRowsRemoved( idx, idx ); + from->removeChild( this ); + from->endRowsRemoved(); + + idx = to->children().count(); + to->beginRowsAdded( idx, idx ); + to->appendChild( this ); + to->endRowsAdded(); + + setParentItem( to ); + } + } +} + + +dynplaylist_ptr +DynamicPlaylistItem::dynPlaylist() const +{ + return m_dynplaylist; +} + +QString +DynamicPlaylistItem::text() const +{ + return m_dynplaylist->title(); +} + +bool +DynamicPlaylistItem::willAcceptDrag( const QMimeData* data ) const +{ + return false; +} + /// Dynamic Playlist Item /* @@ -272,7 +377,8 @@ CategoryAddItem::text() const void CategoryAddItem::activate() { - switch( m_categoryType ) { + switch( m_categoryType ) + { case SourcesModel::PlaylistsCategory: // only show if none is shown yet if( !ViewManager::instance()->isNewPlaylistPageVisible() ) { @@ -281,7 +387,7 @@ CategoryAddItem::activate() } break; case SourcesModel::StationsCategory: - // TODO + APP->mainWindow()->createStation(); break; } } @@ -289,7 +395,15 @@ CategoryAddItem::activate() Qt::ItemFlags CategoryAddItem::flags() const { - return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + switch( m_categoryType ) + { + case SourcesModel::PlaylistsCategory: + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + case SourcesModel::StationsCategory: + default: + return Qt::ItemIsEnabled; + break; + } } QIcon @@ -349,23 +463,23 @@ CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, cons } // create category items if there are playlists to show, or stations to show QList< playlist_ptr > playlists = source->collection()->playlists(); + QList< dynplaylist_ptr > autoplaylists = source->collection()->autoPlaylists(); + QList< dynplaylist_ptr > stations = source->collection()->stations(); - if( !playlists.isEmpty() || source->isLocal() ) { + if( !playlists.isEmpty() || !autoplaylists.isEmpty() || source->isLocal() ) { m_playlists = new CategoryItem( model(), this, SourcesModel::PlaylistsCategory, source->isLocal() ); - // ugh :( we're being added by the model, no need to notify for added rows now -// m_playlists->blockSignals( true ); onPlaylistsAdded( playlists ); -// m_playlists->blockSignals( false ); + onAutoPlaylistsAdded( autoplaylists ); + } + if( !stations.isEmpty() || source->isLocal() ) { + m_stations = new CategoryItem( model(), this, SourcesModel::StationsCategory, source->isLocal() ); + onStationsAdded( stations ); } - - // TODO always show for now, till we actually support stations -// m_stations = new CategoryItem( model(), this, SourcesModel::StationsCategory, source->isLocal() ); if( ViewManager::instance()->pageForCollection( source->collection() ) ) model()->linkSourceItemToPage( this, ViewManager::instance()->pageForCollection( source->collection() ) ); - // HACK to load only for now - source->collection()->dynamicPlaylists(); + // load auto playlists and stations! connect( source.data(), SIGNAL( stats( QVariantMap ) ), this, SIGNAL( updated() ) ); connect( source.data(), SIGNAL( playbackStarted( Tomahawk::query_ptr ) ), this, SIGNAL( updated() ) ); @@ -377,6 +491,16 @@ CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, cons SLOT( onPlaylistsAdded( QList ) ), Qt::QueuedConnection ); connect( source->collection().data(), SIGNAL( playlistsDeleted( QList ) ), SLOT( onPlaylistsDeleted( QList ) ), Qt::QueuedConnection ); + + connect( source->collection().data(), SIGNAL( autoPlaylistsAdded( QList< Tomahawk::dynplaylist_ptr > ) ), + SLOT( onAutoPlaylistsAdded( QList ) ), Qt::QueuedConnection ); + connect( source->collection().data(), SIGNAL( autoPlaylistsDeleted( QList ) ), + SLOT( onAutoPlaylistsDeleted( QList ) ), Qt::QueuedConnection ); + + connect( source->collection().data(), SIGNAL( stationsAdded( QList ) ), + SLOT( onStationsAdded( QList ) ), Qt::QueuedConnection ); + connect( source->collection().data(), SIGNAL( stationsDeleted( QList ) ), + SLOT( onStationsDeleted( QList ) ), Qt::QueuedConnection ); } Tomahawk::source_ptr @@ -412,6 +536,44 @@ CollectionItem::icon() const return QIcon( RESPATH "images/user-avatar.png" ); } +void +CollectionItem::playlistsAddedInternal( SourceTreeItem* parent, const QList< dynplaylist_ptr >& playlists ) +{ + QList< SourceTreeItem* > items; + int addOffset = playlists.first()->author()->isLocal() ? 1 : 0; + + int from = parent->children().count() - addOffset; + parent->beginRowsAdded( from, from + playlists.count() - 1 ); + foreach( const dynplaylist_ptr& p, playlists ) + { + DynamicPlaylistItem* plItem = new DynamicPlaylistItem( model(), parent, p, parent->children().count() - addOffset ); + qDebug() << "Dynamic Playlist added:" << p->title() << p->creator() << p->info(); + p->loadRevision(); + items << plItem; + } + parent->endRowsAdded(); +} + +template< typename T > +void +CollectionItem::playlistsDeletedInternal( SourceTreeItem* parent, const QList< T >& playlists ) +{ + Q_ASSERT( parent ); // How can we delete playlists if we have none? + QList< SourceTreeItem* > items; + foreach( const T& playlist, playlists ) { + int curCount = parent->children().count(); + for( int i = 0; i < curCount; i++ ) { + PlaylistItem* pl = qobject_cast< PlaylistItem* >( parent->children().at( i ) ); + if( pl && pl->playlist() == playlist ) { + parent->beginRowsRemoved( i, i ); + parent->removeChild( pl ); + parent->endRowsRemoved(); + break; + } + } + } +} + void CollectionItem::onPlaylistsAdded( const QList< playlist_ptr >& playlists ) @@ -420,7 +582,10 @@ CollectionItem::onPlaylistsAdded( const QList< playlist_ptr >& playlists ) return; if( !m_playlists ) { // add the category too + int cur = children().count(); + beginRowsAdded( cur, cur ); m_playlists = new CategoryItem( model(), this, SourcesModel::PlaylistsCategory, source()->isLocal() ); + endRowsAdded(); } QList< SourceTreeItem* > items; @@ -441,22 +606,57 @@ CollectionItem::onPlaylistsAdded( const QList< playlist_ptr >& playlists ) void CollectionItem::onPlaylistsDeleted( const QList< playlist_ptr >& playlists ) { - Q_ASSERT( m_playlists ); // How can we delete playlists if we have none? - QList< SourceTreeItem* > items; - foreach( const playlist_ptr& playlist, playlists ) { - int curCount = m_playlists->children().count(); - for( int i = 0; i < curCount; i++ ) { - PlaylistItem* pl = qobject_cast< PlaylistItem* >( m_playlists->children().at( i ) ); - if( pl && pl->playlist() == playlist ) { - m_playlists->beginRowsRemoved( i, i ); - m_playlists->removeChild( pl ); - m_playlists->endRowsRemoved(); - break; - } - } - } + playlistsDeletedInternal( m_playlists, playlists ); } +void +CollectionItem::onAutoPlaylistsAdded( const QList< dynplaylist_ptr >& playlists ) +{ + if( playlists.isEmpty() ) + return; + + if( !m_playlists ) { // add the category too + int cur = children().count(); + beginRowsAdded( cur, cur ); + m_playlists = new CategoryItem( model(), this, SourcesModel::PlaylistsCategory, source()->isLocal() ); + endRowsAdded(); + } + + playlistsAddedInternal( m_playlists, playlists ); +} + +void +CollectionItem::onAutoPlaylistsDeleted( const QList< dynplaylist_ptr >& playlists ) +{ + if( !m_playlists ) + qDebug() << "NO playlist category item for a deleting playlist.."; + + playlistsDeletedInternal( m_playlists, playlists ); +} + +void +CollectionItem::onStationsAdded( const QList< dynplaylist_ptr >& stations ) +{ + if( stations.isEmpty() ) + return; + + if( !m_stations ) { // add the category too + int cur = children().count(); + beginRowsAdded( cur, cur ); + m_stations = new CategoryItem( model(), this, SourcesModel::StationsCategory, source()->isLocal() ); + endRowsAdded(); + } + + playlistsAddedInternal( m_stations, stations ); +} + +void +CollectionItem::onStationsDeleted( const QList< dynplaylist_ptr >& stations ) +{ + playlistsDeletedInternal( m_stations, stations ); +} + + /// Generic page item GenericPageItem::GenericPageItem( SourcesModel* model, SourceTreeItem* parent, const QString& text, const QIcon& icon ) : SourceTreeItem( model, parent, SourcesModel::GenericPage ) diff --git a/src/sourcetree/sourcetreeitem.h b/src/sourcetree/sourcetreeitem.h index fbd08eed1..fe433da9e 100644 --- a/src/sourcetree/sourcetreeitem.h +++ b/src/sourcetree/sourcetreeitem.h @@ -58,6 +58,7 @@ public: void endRowsAdded() { emit childRowsAdded(); } void beginRowsRemoved( int from, int to ) { emit beginChildRowsRemoved( from, to ); } void endRowsRemoved() { emit childRowsRemoved(); } + signals: void updated(); @@ -66,6 +67,10 @@ signals: void beginChildRowsRemoved( int fromRow, int toRow ); void childRowsRemoved(); + +protected: + void setRowType( SourcesModel::RowType t ) { m_type = t; } + void setParentItem( SourceTreeItem* item ) { m_parent = item; } private: SourcesModel::RowType m_type; @@ -133,13 +138,24 @@ public: Tomahawk::source_ptr source() const; + CategoryItem* stationsCategory() const { return m_stations; } + CategoryItem* playlistsCategory() const { return m_playlists; } + void setStationsCategory( CategoryItem* item ) { m_stations = item; } + void setPlaylistsCategory( CategoryItem* item ) { m_playlists = item; } private slots: void onPlaylistsAdded( const QList& playlists ); void onPlaylistsDeleted( const QList& playlists ); + void onAutoPlaylistsAdded( const QList& playlists ); + void onAutoPlaylistsDeleted( const QList& playlists ); + void onStationsAdded( const QList& stations ); + void onStationsDeleted( const QList& stations ); private: - Tomahawk::source_ptr m_source; + void playlistsAddedInternal( SourceTreeItem* parent, const QList< Tomahawk::dynplaylist_ptr >& playlists ); + template< typename T > + void playlistsDeletedInternal( SourceTreeItem* parent, const QList< T >& playlists ); + Tomahawk::source_ptr m_source; CategoryItem* m_playlists; CategoryItem* m_stations; }; @@ -171,24 +187,27 @@ private: Tomahawk::playlist_ptr m_playlist; }; -/* -class DynPlaylistItem : public PlaylistItem +// can be a station or an auto playlist +class DynamicPlaylistItem : public PlaylistItem { Q_OBJECT public: - DynPlaylistItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::dynplaylist_ptr& pl ); + DynamicPlaylistItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::dynplaylist_ptr& pl, int index = -1 ); + virtual ~DynamicPlaylistItem(); virtual QString text() const; - virtual Tomahawk::playlist_ptr playlist() const; -// Tomahawk::dynplaylist_ptr playlist() const; + Tomahawk::dynplaylist_ptr dynPlaylist() const; + virtual bool willAcceptDrag( const QMimeData* data ) const; virtual void activate(); private slots: void onDynamicPlaylistLoaded( Tomahawk::DynamicPlaylistRevision revision ); private: + void checkReparentHackNeeded( const DynamicPlaylistRevision& rev ); + Tomahawk::dynplaylist_ptr m_dynplaylist; -};*/ +}; // generic item that has some name, some text, and calls a certain slot when activated. badabing! class GenericPageItem : public SourceTreeItem diff --git a/src/sourcetree/sourcetreeview.cpp b/src/sourcetree/sourcetreeview.cpp index 5a3688894..b4d9ef18f 100644 --- a/src/sourcetree/sourcetreeview.cpp +++ b/src/sourcetree/sourcetreeview.cpp @@ -105,19 +105,6 @@ SourceTreeView::SourceTreeView( QWidget* parent ) // connect( selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), SLOT( onSelectionChanged() ) ); hideOfflineSources(); - - connect( ViewManager::instance(), SIGNAL( playlistActivated( Tomahawk::playlist_ptr ) ), - SLOT( onPlaylistActivated( Tomahawk::playlist_ptr ) ) ); -// connect( PlaylistManager::instance(), SIGNAL( dynamicPlaylistActivated( Tomahawk::dynplaylist_ptr ) ), -// SLOT( onDynamicPlaylistActivated( Tomahawk::dynplaylist_ptr ) ) ); - connect( ViewManager::instance(), SIGNAL( collectionActivated( Tomahawk::collection_ptr ) ), - SLOT( onCollectionActivated( Tomahawk::collection_ptr ) ) ); - connect( ViewManager::instance(), SIGNAL( superCollectionActivated() ), - SLOT( onSuperCollectionActivated() ) ); - connect( ViewManager::instance(), SIGNAL( tempPageActivated() ), - SLOT( onTempPageActivated() ) ); - connect( ViewManager::instance(), SIGNAL( newPlaylistActivated() ), - SLOT( onNewPlaylistPageActivated() ) ); } @@ -133,7 +120,7 @@ SourceTreeView::setupMenus() bool readonly = true; SourcesModel::RowType type = ( SourcesModel::RowType )model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ).toInt(); - if ( type == SourcesModel::StaticPlaylist ) + if ( type == SourcesModel::StaticPlaylist || type == SourcesModel::AutomaticPlaylist || type == SourcesModel::Station ) { PlaylistItem* item = itemFromIndex< PlaylistItem >( m_contextMenuIndex ); @@ -166,65 +153,6 @@ SourceTreeView::hideOfflineSources() m_proxyModel->hideOfflineSources(); } - -void -SourceTreeView::onPlaylistActivated( const Tomahawk::playlist_ptr& playlist ) -{ -// QModelIndex idx = m_proxyModel->mapFromSource( m_model->indexFromPlaylist( playlist ) ); -// if ( idx.isValid() ) -// { -// selectionModel()->select( idx, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Current ); -// setCurrentIndex( idx ); -// } -} - -/* -void -SourceTreeView::onDynamicPlaylistActivated( const Tomahawk::dynplaylist_ptr& playlist ) -{ - QModelIndex idx = m_proxyModel->mapFromSource( m_model->dynamicPlaylistToIndex( playlist ) ); - if ( idx.isValid() ) - { - setCurrentIndex( idx ); - } -}*/ - - -void -SourceTreeView::onCollectionActivated( const Tomahawk::collection_ptr& collection ) -{ -// QModelIndex idx = m_proxyModel->mapFromSource( m_model->collectionToIndex( collection ) ); -// if ( idx.isValid() ) -// { -// setCurrentIndex( idx ); -// } -} - - -void -SourceTreeView::onSuperCollectionActivated() -{ -// QModelIndex idx = m_proxyModel->index( 0, 0 ); -// if ( idx.isValid() ) -// { -// setCurrentIndex( idx ); -// } -} - - -void -SourceTreeView::onTempPageActivated() -{ - clearSelection(); -} - -void -SourceTreeView::onNewPlaylistPageActivated() -{ - // nothing atm -} - - void SourceTreeView::onItemActivated( const QModelIndex& index ) { @@ -278,6 +206,11 @@ SourceTreeView::deletePlaylist() PlaylistItem* item = itemFromIndex< PlaylistItem >( m_contextMenuIndex ); playlist_ptr playlist = item->playlist(); Playlist::remove( playlist ); + } else if( type == SourcesModel::AutomaticPlaylist || type == SourcesModel::Station ) + { + DynamicPlaylistItem* item = itemFromIndex< DynamicPlaylistItem >( m_contextMenuIndex ); + dynplaylist_ptr playlist = item->dynPlaylist(); + DynamicPlaylist::remove( playlist ); } } @@ -300,7 +233,9 @@ SourceTreeView::onCustomContextMenu( const QPoint& pos ) setupMenus(); - if ( model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::StaticPlaylist ) + if ( model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::StaticPlaylist || + model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::AutomaticPlaylist || + model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::Station ) { PlaylistItem* item = itemFromIndex< PlaylistItem >( m_contextMenuIndex ); if( item->playlist()->author()->isLocal() ) diff --git a/src/sourcetree/sourcetreeview.h b/src/sourcetree/sourcetreeview.h index 9952ddfa1..83a5d5fc4 100644 --- a/src/sourcetree/sourcetreeview.h +++ b/src/sourcetree/sourcetreeview.h @@ -46,14 +46,6 @@ signals: void onOffline( const QModelIndex& index ); private slots: - void onPlaylistActivated( const Tomahawk::playlist_ptr& playlist ); -// void onDynamicPlaylistActivated( const Tomahawk::dynplaylist_ptr& playlist ); - - void onCollectionActivated( const Tomahawk::collection_ptr& collection ); - void onSuperCollectionActivated(); - void onTempPageActivated(); - void onNewPlaylistPageActivated(); - void onItemExpanded( const QModelIndex& idx ); void onItemActivated( const QModelIndex& index ); void selectRequest( const QModelIndex& idx ); diff --git a/src/tomahawkwindow.cpp b/src/tomahawkwindow.cpp index 1c7877d68..b4c95a7e2 100644 --- a/src/tomahawkwindow.cpp +++ b/src/tomahawkwindow.cpp @@ -400,7 +400,7 @@ TomahawkWindow::createAutomaticPlaylist() QString id = uuid(); QString info = ""; // FIXME QString creator = "someone"; // FIXME - dynplaylist_ptr playlist = DynamicPlaylist::create( author, id, name, info, creator, false ); + dynplaylist_ptr playlist = DynamicPlaylist::create( author, id, name, info, creator, Static, false ); playlist->setMode( Static ); playlist->createNewRevision( uuid(), playlist->currentrevision(), playlist->type(), playlist->generator()->controls(), playlist->entries() ); ViewManager::instance()->show( playlist ); @@ -419,7 +419,7 @@ TomahawkWindow::createStation() QString id = uuid(); QString info = ""; // FIXME QString creator = "someone"; // FIXME - dynplaylist_ptr playlist = DynamicPlaylist::create( author, id, name, info, creator, false ); + dynplaylist_ptr playlist = DynamicPlaylist::create( author, id, name, info, creator, OnDemand, false ); playlist->setMode( OnDemand ); playlist->createNewRevision( uuid(), playlist->currentrevision(), playlist->type(), playlist->generator()->controls() ); ViewManager::instance()->show( playlist );