/src/libtomahawk/Playlist.cpp
http://github.com/tomahawk-player/tomahawk · C++ · 959 lines · 717 code · 190 blank · 52 comment · 56 complexity · d3eda2a3ef93461dfd716af9840c0f1e MD5 · raw file
- /* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
- *
- * Copyright 2010-2015, Christian Muehlhaeuser <muesli@tomahawk-player.org>
- * Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
- * Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
- #include "Playlist_p.h"
- #include "collection/Collection.h"
- #include "database/Database.h"
- #include "database/DatabaseCommand_LoadPlaylistEntries.h"
- #include "database/DatabaseCommand_SetPlaylistRevision.h"
- #include "database/DatabaseCommand_CreatePlaylist.h"
- #include "database/DatabaseCommand_DeletePlaylist.h"
- #include "database/DatabaseCommand_RenamePlaylist.h"
- #include "playlist/PlaylistUpdaterInterface.h"
- #include "playlist/PlaylistModel.h"
- #include "utils/Logger.h"
- #include "utils/Closure.h"
- #include "Pipeline.h"
- #include "PlaylistEntry.h"
- #include "PlaylistPlaylistInterface.h"
- #include "Source.h"
- #include "SourceList.h"
- #include <QDomDocument>
- #include <QDomElement>
- using namespace Tomahawk;
- static QSharedPointer<PlaylistRemovalHandler> s_removalHandler;
- Playlist::Playlist( const source_ptr& author )
- : d_ptr( new PlaylistPrivate( this, author ) )
- {
- }
- // used when loading from DB:
- Playlist::Playlist( const source_ptr& src,
- const QString& currentrevision,
- const QString& title,
- const QString& info,
- const QString& creator,
- uint createdOn,
- bool shared,
- int lastmod,
- const QString& guid )
- : QObject()
- , d_ptr( new PlaylistPrivate( this, src, currentrevision, title, info, creator, createdOn, shared, lastmod, guid ) )
- {
- init();
- }
- Playlist::Playlist( const source_ptr& author,
- const QString& guid,
- const QString& title,
- const QString& info,
- const QString& creator,
- bool shared,
- const QList< Tomahawk::plentry_ptr >& entries )
- : QObject()
- , d_ptr( new PlaylistPrivate( this, author, guid, title, info, creator, shared, entries ) )
- {
- init();
- }
- Playlist::Playlist( const source_ptr& author,
- const QString& guid,
- const QString& title,
- const QString& info,
- const QString& creator,
- bool shared)
- : QObject()
- , d_ptr( new PlaylistPrivate( this, author, guid, title, info, creator, shared, QList< Tomahawk::plentry_ptr >() ) )
- {
- init();
- }
- void
- Playlist::init()
- {
- Q_D( Playlist );
- d->busy = false;
- d->deleted = false;
- d->locallyChanged = false;
- d->loaded = false;
- connect( Pipeline::instance(), SIGNAL( idle() ), SLOT( onResolvingFinished() ) );
- }
- Playlist::~Playlist()
- {
- delete d_ptr;
- }
- QSharedPointer<PlaylistRemovalHandler> Playlist::removalHandler()
- {
- if ( s_removalHandler.isNull() )
- {
- s_removalHandler = QSharedPointer<PlaylistRemovalHandler>( new PlaylistRemovalHandler() );
- }
- return s_removalHandler;
- }
- playlist_ptr
- Playlist::create( const source_ptr& author,
- const QString& guid,
- const QString& title,
- const QString& info,
- const QString& creator,
- bool shared,
- const QList<Tomahawk::query_ptr>& queries )
- {
- QList< plentry_ptr > entries;
- foreach( const Tomahawk::query_ptr& query, queries )
- {
- plentry_ptr p( new PlaylistEntry );
- p->setGuid( uuid() );
- p->setDuration( query->track()->duration() );
- p->setLastmodified( 0 );
- p->setAnnotation( query->property( "annotation" ).toString() );
- p->setQuery( query );
- entries << p;
- }
- playlist_ptr playlist( new Playlist( author, guid, title, info, creator, shared, entries ), &QObject::deleteLater );
- playlist->setWeakSelf( playlist.toWeakRef() );
- // save to DB in the background
- // Watch for the created() signal if you need to be sure it's written.
- //
- // When a playlist is created it will reportCreated(), adding it to the
- // collection it belongs to and emitting the appropriate signal.
- // When we create a new playlist for the local Source.here we call reportCreated()
- // immediately, so the GUI can reflect the new playlist without waiting for the DB sync
- //
- // When createplaylist DBOPs come from peers, the postCommitHook will call
- // reportCreated for us automatically, which should cause new playlists to be added to the GUI.
- DatabaseCommand_CreatePlaylist* cmd = new DatabaseCommand_CreatePlaylist( author, playlist );
- connect( cmd, SIGNAL( finished() ), playlist.data(), SIGNAL( created() ) );
- Database::instance()->enqueue( dbcmd_ptr(cmd) );
- playlist->reportCreated( playlist );
- return playlist;
- }
- playlist_ptr
- Playlist::get( const QString& guid )
- {
- playlist_ptr p;
- foreach( const Tomahawk::source_ptr& source, SourceList::instance()->sources() )
- {
- p = source->dbCollection()->playlist( guid );
- if ( !p )
- p = source->dbCollection()->autoPlaylist( guid );
- if ( !p )
- p = source->dbCollection()->station( guid );
- if ( p )
- return p;
- }
- return p;
- }
- void
- Playlist::rename( const QString& title )
- {
- DatabaseCommand_RenamePlaylist* cmd = new DatabaseCommand_RenamePlaylist( author(), guid(), title );
- Database::instance()->enqueue( Tomahawk::dbcmd_ptr(cmd) );
- }
- void
- Playlist::setTitle( const QString& title )
- {
- Q_D( Playlist );
- if ( title == d->title )
- return;
- const QString oldTitle = d->title;
- d->title = title;
- emit changed();
- emit renamed( d->title, oldTitle );
- }
- void
- Playlist::reportCreated( const playlist_ptr& self )
- {
- Q_D( Playlist );
- Q_ASSERT( self.data() == this );
- d->source->dbCollection()->addPlaylist( self );
- }
- void
- Playlist::reportDeleted( const Tomahawk::playlist_ptr& self )
- {
- Q_D( Playlist );
- Q_ASSERT( self.data() == this );
- if ( !d->updaters.isEmpty() )
- {
- foreach( PlaylistUpdaterInterface* updater, d->updaters )
- {
- updater->remove();
- }
- }
- d->deleted = true;
- d->source->dbCollection()->deletePlaylist( self );
- emit deleted( self );
- }
- void
- Playlist::addUpdater( PlaylistUpdaterInterface* updater )
- {
- Q_D( Playlist );
- d->updaters << updater;
- connect( updater, SIGNAL( changed() ), this, SIGNAL( changed() ), Qt::UniqueConnection );
- connect( updater, SIGNAL( destroyed( QObject* ) ), this, SIGNAL( changed() ), Qt::QueuedConnection );
- emit changed();
- }
- void
- Playlist::removeUpdater( PlaylistUpdaterInterface* updater )
- {
- Q_D( Playlist );
- d->updaters.removeAll( updater );
- disconnect( updater, SIGNAL( changed() ), this, SIGNAL( changed() ) );
- disconnect( updater, SIGNAL( destroyed( QObject* ) ), this, SIGNAL( changed() ) );
- emit changed();
- }
- bool
- Playlist::hasCustomDeleter() const
- {
- Q_D( const Playlist );
- foreach ( PlaylistUpdaterInterface* updater, d->updaters )
- {
- if ( updater->hasCustomDeleter() )
- return true;
- }
- return false;
- }
- void
- Playlist::loadRevision( const QString& rev )
- {
- // qDebug() << Q_FUNC_INFO << currentrevision() << rev << m_title;
- setBusy( true );
- DatabaseCommand_LoadPlaylistEntries* cmd =
- new DatabaseCommand_LoadPlaylistEntries( rev.isEmpty() ? currentrevision() : rev );
- connect( cmd, SIGNAL( done( const QString&,
- const QList<QString>&,
- const QList<QString>&,
- bool,
- const QMap< QString, Tomahawk::plentry_ptr >&,
- bool ) ),
- SLOT( setRevision( const QString&,
- const QList<QString>&,
- const QList<QString>&,
- bool,
- const QMap< QString, Tomahawk::plentry_ptr >&,
- bool ) ) );
- Database::instance()->enqueue( Tomahawk::dbcmd_ptr( cmd ) );
- }
- //public, model can call this if user changes a playlist:
- void
- Playlist::createNewRevision( const QString& newrev, const QString& oldrev, const QList< plentry_ptr >& entries )
- {
- Q_D( Playlist );
- tDebug() << Q_FUNC_INFO << newrev << oldrev << entries.count();
- Q_ASSERT( d->source->isLocal() || newrev == oldrev );
- if ( busy() )
- {
- d->revisionQueue.enqueue( RevisionQueueItem( newrev, oldrev, entries, oldrev == currentrevision() ) );
- return;
- }
- if ( newrev != oldrev )
- setBusy( true );
- // calc list of newly added entries:
- QList<plentry_ptr> added = newEntries( entries );
- QStringList orderedguids;
- qDebug() << "Inserting ordered GUIDs:";
- foreach( const plentry_ptr& p, entries )
- {
- qDebug() << p->guid() << p->query()->track()->toString();
- orderedguids << p->guid();
- }
- foreach( const plentry_ptr& p, added )
- qDebug() << p->guid();
- // source making the change (local user in this case)
- source_ptr author = SourceList::instance()->getLocal();
- // command writes new rev to DB and calls setRevision, which emits our signal
- DatabaseCommand_SetPlaylistRevision* cmd =
- new DatabaseCommand_SetPlaylistRevision( author,
- guid(),
- newrev,
- oldrev,
- orderedguids,
- added,
- entries );
- connect( cmd, SIGNAL( finished() ),
- this, SLOT( setPlaylistRevisionFinished() ) );
- if ( d->queuedSetPlaylistRevision )
- {
- d->queuedSetPlaylistRevisionCmds.enqueue( cmd );
- }
- else
- {
- d->queuedSetPlaylistRevision = true;
- Database::instance()->enqueue( Tomahawk::dbcmd_ptr( cmd ) );
- }
- }
- void
- Playlist::updateEntries( const QString& newrev, const QString& oldrev, const QList< plentry_ptr >& entries )
- {
- Q_D( Playlist );
- tDebug() << Q_FUNC_INFO << newrev << oldrev << entries.count();
- Q_ASSERT( d->source->isLocal() || newrev == oldrev );
- if ( busy() )
- {
- d->updateQueue.enqueue( RevisionQueueItem( newrev, oldrev, entries, oldrev == currentrevision() ) );
- return;
- }
- if ( newrev != oldrev )
- setBusy( true );
- QStringList orderedguids;
- foreach( const plentry_ptr& p, d->entries )
- {
- orderedguids << p->guid();
- }
- qDebug() << "Updating playlist metadata:" << entries;
- DatabaseCommand_SetPlaylistRevision* cmd =
- new DatabaseCommand_SetPlaylistRevision( SourceList::instance()->getLocal(),
- guid(),
- newrev,
- oldrev,
- orderedguids,
- entries );
- connect( cmd, SIGNAL( finished() ),
- this, SLOT( setPlaylistRevisionFinished() ) );
- if ( d->queuedSetPlaylistRevision )
- {
- d->queuedSetPlaylistRevisionCmds.enqueue( cmd );
- }
- else
- {
- d->queuedSetPlaylistRevision = true;
- Database::instance()->enqueue( Tomahawk::dbcmd_ptr( cmd ) );
- }
- }
- // private, called when we loadRevision, or by our friend class DatabaseCommand_SetPlaylistRevision
- // used to save new revision data (either originating locally, or via network msg for syncing)
- void
- Playlist::setRevision( const QString& rev,
- const QList<QString>& neworderedguids,
- const QList<QString>& oldorderedguids,
- bool is_newest_rev,
- const QMap< QString, Tomahawk::plentry_ptr >& addedmap,
- bool applied )
- {
- Q_D( Playlist );
- if ( QThread::currentThread() != thread() )
- {
- QMetaObject::invokeMethod( this,
- "setRevision",
- Qt::BlockingQueuedConnection,
- Q_ARG( QString, rev ),
- Q_ARG( QList<QString>, neworderedguids ),
- Q_ARG( QList<QString>, oldorderedguids ),
- Q_ARG( bool, is_newest_rev ),
- QGenericArgument( "QMap< QString,Tomahawk::plentry_ptr >", (const void*)&addedmap ),
- Q_ARG( bool, applied )
- );
- return;
- }
- PlaylistRevision pr = setNewRevision( rev, neworderedguids, oldorderedguids, is_newest_rev, addedmap );
- Q_ASSERT( applied );
- if ( applied )
- d->currentrevision = rev;
- pr.applied = applied;
- foreach( const plentry_ptr& entry, d->entries )
- {
- connect( entry.data(), SIGNAL( resultChanged() ), SLOT( onResultsChanged() ), Qt::UniqueConnection );
- }
- setBusy( false );
- setLoaded( true );
- if ( !d->initEntries.isEmpty() && currentrevision().isEmpty() )
- {
- // add initial tracks
- createNewRevision( uuid(), currentrevision(), d->initEntries );
- d->initEntries.clear();
- }
- else
- emit revisionLoaded( pr );
- checkRevisionQueue();
- }
- PlaylistRevision
- Playlist::setNewRevision( const QString& rev,
- const QList<QString>& neworderedguids,
- const QList<QString>& oldorderedguids,
- bool is_newest_rev,
- const QMap< QString, Tomahawk::plentry_ptr >& addedmap )
- {
- Q_D( Playlist );
- Q_UNUSED( oldorderedguids );
- Q_UNUSED( is_newest_rev );
- // build up correctly ordered new list of plentry_ptrs from
- // existing ones, and the ones that have been added
- QMap<QString, plentry_ptr> entriesmap;
- foreach ( const plentry_ptr& p, d->entries )
- {
- entriesmap.insert( p->guid(), p );
- }
- // re-build m_entries from neworderedguids. plentries come either from the old m_entries OR addedmap.
- d->entries.clear();
- foreach ( const QString& id, neworderedguids )
- {
- if ( entriesmap.contains( id ) )
- {
- d->entries.append( entriesmap.value( id ) );
- }
- else if ( addedmap.contains( id ) )
- {
- d->entries.append( addedmap.value( id ) );
- }
- else
- {
- tDebug() << "id:" << id;
- tDebug() << "newordered:" << neworderedguids.count() << neworderedguids;
- tDebug() << "entriesmap:" << entriesmap.count() << entriesmap;
- tDebug() << "addedmap:" << addedmap.count() << addedmap;
- tDebug() << "m_entries" << d->entries;
- tLog() << "Playlist error for playlist with guid" << guid() << "from source" << author()->friendlyName();
- // Q_ASSERT( false ); // XXX
- }
- }
- PlaylistRevision pr;
- pr.oldrevisionguid = d->currentrevision;
- pr.revisionguid = rev;
- pr.added = addedmap.values();
- pr.newlist = d->entries;
- return pr;
- }
- void
- Playlist::removeFromDatabase()
- {
- Q_D( Playlist );
- emit aboutToBeDeleted( d->weakSelf.toStrongRef() );
- DatabaseCommand_DeletePlaylist* cmd = new DatabaseCommand_DeletePlaylist( d->source, d->guid );
- Database::instance()->enqueue( Tomahawk::dbcmd_ptr( cmd ) );
- }
- Playlist::Playlist( PlaylistPrivate *d )
- : d_ptr( d )
- {
- init();
- }
- source_ptr
- Playlist::author() const
- {
- Q_D( const Playlist );
- return d->source;
- }
- void
- Playlist::resolve()
- {
- Q_D( Playlist );
- QList< query_ptr > qlist;
- foreach( const plentry_ptr& p, d->entries )
- {
- qlist << p->query();
- }
- Pipeline::instance()->resolve( qlist );
- }
- void
- Playlist::onResultsChanged()
- {
- Q_D( Playlist );
- d->locallyChanged = true;
- }
- void
- Playlist::onResolvingFinished()
- {
- Q_D( Playlist );
- if ( d->locallyChanged && !d->deleted )
- {
- d->locallyChanged = false;
- createNewRevision( currentrevision(), currentrevision(), d->entries );
- }
- }
- void
- Playlist::setPlaylistRevisionFinished()
- {
- Q_D( Playlist );
- if ( !d->queuedSetPlaylistRevisionCmds.isEmpty() )
- {
- DatabaseCommand_SetPlaylistRevision* cmd = d->queuedSetPlaylistRevisionCmds.dequeue();
- // Update oldrev to currentRevision so that optimistic locking works correctly.
- cmd->setOldrev( currentrevision() );
- Database::instance()->enqueue( Tomahawk::dbcmd_ptr( cmd ) );
- }
- else
- {
- d->queuedSetPlaylistRevision = false;
- }
- }
- void
- Playlist::addEntry( const query_ptr& query )
- {
- QList<query_ptr> queries;
- queries << query;
- addEntries( queries );
- }
- void
- Playlist::addEntries( const QList<query_ptr>& queries )
- {
- Q_D( Playlist );
- if ( !d->loaded )
- {
- tDebug() << Q_FUNC_INFO << "Queueing addEntries call!";
- loadRevision();
- d->queuedOps << NewClosure( 0, "", this, SLOT( addEntries( QList<Tomahawk::query_ptr> ) ), queries );
- return;
- }
- const QList<plentry_ptr> el = entriesFromQueries( queries );
- const int prevSize = d->entries.size();
- QString newrev = uuid();
- createNewRevision( newrev, d->currentrevision, el );
- // We are appending at end, so notify listeners.
- // PlaylistModel also emits during appends, but since we call
- // createNewRevision, it reloads instead of appends.
- const QList<plentry_ptr> added = el.mid( prevSize );
- tDebug( LOGVERBOSE ) << "Playlist got" << queries.size() << "tracks added, emitting tracksInserted with:" << added.size() << "at pos:" << prevSize - 1;
- emit tracksInserted( added, prevSize );
- }
- void
- Playlist::insertEntries( const QList< query_ptr >& queries, const int position )
- {
- Q_D( Playlist );
- if ( !d->loaded )
- {
- tDebug() << Q_FUNC_INFO << "Queueing insertEntries call!";
- loadRevision();
- d->queuedOps << NewClosure( 0, "", this, SLOT( insertEntries( QList<Tomahawk::query_ptr>, int ) ), queries, position );
- return;
- }
- QList<plentry_ptr> toInsert = entriesFromQueries( queries, true );
- QList<plentry_ptr> entries = d->entries;
- Q_ASSERT( position <= d->entries.size() );
- if ( position > d->entries.size() )
- {
- tDebug() << "ERROR trying to insert tracks past end of playlist! Appending!";
- addEntries( queries );
- return;
- }
- for ( int i = toInsert.size()-1; i >= 0; --i )
- entries.insert( position, toInsert.at(i) );
- createNewRevision( uuid(), d->currentrevision, entries );
- // We are appending at end, so notify listeners.
- // PlaylistModel also emits during appends, but since we call
- // createNewRevision, it reloads instead of appends.
- qDebug() << "Playlist got" << toInsert.size() << "tracks added, emitting tracksInserted at pos:" << position;
- emit tracksInserted( toInsert, position );
- }
- QList<plentry_ptr>
- Playlist::entriesFromQueries( const QList<Tomahawk::query_ptr>& queries, bool clearFirst )
- {
- QList<plentry_ptr> el;
- if ( !clearFirst )
- el = entries();
- foreach( const query_ptr& query, queries )
- {
- plentry_ptr e( new PlaylistEntry() );
- e->setGuid( uuid() );
- e->setDuration( query->track()->duration() );
- e->setLastmodified( 0 );
- QString annotation = "";
- if ( !query->property( "annotation" ).toString().isEmpty() )
- annotation = query->property( "annotation" ).toString();
- e->setAnnotation( annotation ); // FIXME
- e->setQuery( query );
- el << e;
- }
- return el;
- }
- QList< plentry_ptr >
- Playlist::newEntries( const QList< plentry_ptr >& entries )
- {
- Q_D( Playlist );
- QSet<QString> currentguids;
- foreach( const plentry_ptr& p, d->entries )
- currentguids.insert( p->guid() ); // could be cached as member?
- // calc list of newly added entries:
- QList<plentry_ptr> added;
- foreach( const plentry_ptr& p, entries )
- {
- if ( !currentguids.contains( p->guid() ) )
- added << p;
- }
- return added;
- }
- void
- Playlist::setBusy( bool b )
- {
- Q_D( Playlist );
- d->busy = b;
- emit changed();
- }
- void
- Playlist::setLoaded( bool b )
- {
- Q_D( Playlist );
- d->loaded = b;
- }
- void
- Playlist::checkRevisionQueue()
- {
- Q_D( Playlist );
- if ( !d->revisionQueue.isEmpty() )
- {
- RevisionQueueItem item = d->revisionQueue.dequeue();
- if ( item.oldRev != currentrevision() && item.applyToTip )
- {
- // this was applied to the then-latest, but the already-running operation changed it so it's out of date now. fix it
- if ( item.oldRev == item.newRev )
- {
- checkRevisionQueue();
- return;
- }
- item.oldRev = currentrevision();
- }
- createNewRevision( item.newRev, item.oldRev, item.entries );
- }
- if ( !d->updateQueue.isEmpty() )
- {
- RevisionQueueItem item = d->updateQueue.dequeue();
- if ( item.oldRev != currentrevision() && item.applyToTip )
- {
- // this was applied to the then-latest, but the already-running operation changed it so it's out of date now. fix it
- if ( item.oldRev == item.newRev )
- {
- checkRevisionQueue();
- return;
- }
- item.oldRev = currentrevision();
- }
- updateEntries( item.newRev, item.oldRev, item.entries );
- }
- if ( !d->queuedOps.isEmpty() )
- {
- _detail::Closure* next = d->queuedOps.dequeue();
- next->forceInvoke();
- }
- }
- void
- Playlist::setWeakSelf( QWeakPointer< Playlist > self )
- {
- Q_D( Playlist );
- d->weakSelf = self;
- }
- Tomahawk::playlistinterface_ptr
- Playlist::playlistInterface()
- {
- Q_D( Playlist );
- if ( d->playlistInterface.isNull() )
- {
- d->playlistInterface = Tomahawk::playlistinterface_ptr( new Tomahawk::PlaylistPlaylistInterface( this ) );
- }
- return d->playlistInterface;
- }
- QString
- Playlist::currentrevision() const
- {
- Q_D( const Playlist );
- return d->currentrevision;
- }
- QString
- Playlist::title() const
- {
- Q_D( const Playlist );
- return d->title;
- }
- QString
- Playlist::info() const
- {
- Q_D( const Playlist );
- return d->info;
- }
- QString
- Playlist::creator() const
- {
- Q_D( const Playlist );
- return d->creator;
- }
- QString
- Playlist::guid() const
- {
- Q_D( const Playlist );
- return d->guid;
- }
- bool
- Playlist::shared() const
- {
- Q_D( const Playlist );
- return d->shared;
- }
- unsigned int
- Playlist::lastmodified() const
- {
- Q_D( const Playlist );
- return d->lastmodified;
- }
- uint
- Playlist::createdOn() const
- {
- Q_D( const Playlist );
- return d->createdOn;
- }
- bool
- Playlist::busy() const
- {
- Q_D( const Playlist );
- return d->busy;
- }
- bool
- Playlist::loaded() const
- {
- Q_D( const Playlist );
- return d->loaded;
- }
- const QList<plentry_ptr>&
- Playlist::entries()
- {
- Q_D( const Playlist );
- return d->entries;
- }
- void
- Playlist::setCurrentrevision( const QString& s )
- {
- Q_D( Playlist );
- d->currentrevision = s;
- }
- void
- Playlist::setInfo( const QString& s )
- {
- Q_D( Playlist );
- d->info = s;
- }
- void
- Playlist::setCreator( const QString& s )
- {
- Q_D( Playlist );
- d->creator = s;
- }
- void
- Playlist::setGuid( const QString& s )
- {
- Q_D( Playlist );
- d->guid = s;
- }
- void
- Playlist::setShared( bool b )
- {
- Q_D( Playlist );
- d->shared = b;
- }
- void
- Playlist::setCreatedOn( uint createdOn )
- {
- Q_D( Playlist );
- d->createdOn = createdOn;
- }
- QList<PlaylistUpdaterInterface *>
- Playlist::updaters() const
- {
- Q_D( const Playlist );
- return d->updaters;
- }
- void
- PlaylistRemovalHandler::remove( const playlist_ptr& playlist )
- {
- playlist->removeFromDatabase();
- }
- PlaylistRemovalHandler::PlaylistRemovalHandler()
- {
- }