File indexing completed on 2024-05-19 04:49:50

0001 /****************************************************************************************
0002  * Copyright (c) 2008 Nikolaj Hald Nielsen <nhn@kde.org>                                *
0003  * Copyright (c) 2008 Soren Harward <stharward@gmail.com>                               *
0004  * Copyright (c) 2009 Téo Mrnjavac <teo@kde.org>                                        *
0005  * Copyright (c) 2010 Nanno Langstraat <langstr@gmail.com>                              *
0006  *                                                                                      *
0007  * This program is free software; you can redistribute it and/or modify it under        *
0008  * the terms of the GNU General Public License as published by the Free Software        *
0009  * Foundation; either version 2 of the License, or (at your option) version 3 or        *
0010  * any later version accepted by the membership of KDE e.V. (or its successor approved  *
0011  * by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of  *
0012  * version 3 of the license.                                                            *
0013  *                                                                                      *
0014  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0015  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0016  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0017  *                                                                                      *
0018  * You should have received a copy of the GNU General Public License along with         *
0019  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0020  ****************************************************************************************/
0021 
0022 #define DEBUG_PREFIX "Playlist::AlbumNavigator"
0023 
0024 #include "AlbumNavigator.h"
0025 
0026 #include "playlist/PlaylistModelStack.h"
0027 
0028 #include "core/support/Debug.h"
0029 #include "core/meta/Meta.h"
0030 
0031 #include <algorithm>
0032 
0033 
0034 void
0035 Playlist::AlbumNavigator::notifyItemsInserted( const QSet<quint64> &insertedItems )
0036 {
0037     DEBUG_BLOCK
0038 
0039     QList<AlbumId> oldAlbumList = m_itemsPerAlbum.uniqueKeys();
0040     QSet<AlbumId> oldAlbums(oldAlbumList.begin(), oldAlbumList.end());
0041     QSet<AlbumId> modifiedAlbums;
0042 
0043     foreach( quint64 insertedItem, insertedItems )
0044     {
0045         AlbumId album = albumForItem( insertedItem );
0046         m_itemsPerAlbum[album].append( insertedItem ); // conveniently creates an empty list if none exists
0047         modifiedAlbums.insert( album );
0048     }
0049 
0050     foreach( AlbumId album, modifiedAlbums )
0051         std::stable_sort( m_itemsPerAlbum[album].begin(), m_itemsPerAlbum[album].end(), itemLessThan );
0052 
0053     notifyAlbumsInserted( ( modifiedAlbums - oldAlbums ).values() );
0054 }
0055 
0056 void
0057 Playlist::AlbumNavigator::notifyItemsRemoved( const QSet<quint64> &removedItems )
0058 {
0059     DEBUG_BLOCK
0060 
0061     foreach( quint64 removedItem, removedItems )
0062     {
0063         AlbumId album = albumForItem( removedItem );
0064 
0065         // Try not to lose our position in the playlist: if we're losing 'currentItem()', substitute the next "planned item".
0066         if ( removedItem == currentItem() )
0067         {
0068             planOne();    // Could select 'removedItem' again; in that case our parent will 'setCurrentItem( 0 )'.
0069             if ( !m_plannedItems.isEmpty() )
0070                 setCurrentItem( m_plannedItems.first() );
0071         }
0072 
0073         m_plannedItems.removeAll( removedItem );    // We only need to do this because we call 'planOne()' in this loop.
0074 
0075         // Maintain 'm_itemsPerAlbum'
0076         ItemList itemsInAlbum = m_itemsPerAlbum.value( album );
0077         itemsInAlbum.removeAll( removedItem );
0078         if ( itemsInAlbum.isEmpty() )
0079         {
0080             m_itemsPerAlbum.remove( album );
0081             m_plannedAlbums.removeAll( album );
0082         }
0083         else
0084             m_itemsPerAlbum.insert( album, itemsInAlbum );    // Replace old list with the edited copy.
0085 
0086         // Maintain 'm_albumForItem'.
0087         m_albumForItem.remove( removedItem );
0088     }
0089 }
0090 
0091 Playlist::AlbumNavigator::AlbumId
0092 Playlist::AlbumNavigator::albumForItem( const quint64 &item )
0093 {
0094     if ( m_albumForItem.contains( item ) )
0095         return m_albumForItem.value( item );
0096     else
0097     {
0098         AlbumId album;
0099 
0100         Meta::TrackPtr track = m_model->trackForId( item );
0101         if ( track )
0102         {
0103             Meta::AlbumPtr metaAlbum = track->album();
0104             if ( metaAlbum )
0105                 album = metaAlbum->name();    // See comment for 'typedef AlbumId'.
0106         }
0107 
0108         m_albumForItem.insert( item, album );
0109         return album;
0110     }
0111 }
0112 
0113 bool
0114 Playlist::AlbumNavigator::itemLessThan( const quint64 &item1, const quint64 &item2 )
0115 {
0116     // Somewhat nasty to hard-code the model like this, but 'qStableSort()' doesn't give us a way to pass 'm_model'.
0117 
0118     AbstractModel *model = The::playlist();
0119 
0120     Meta::TrackPtr track1 = model->trackForId( item1 );
0121     Meta::TrackPtr track2 = model->trackForId( item2 );
0122 
0123     return Meta::Track::lessThan( track1, track2 );
0124 }