File indexing completed on 2024-05-19 04:48:42

0001 /****************************************************************************************
0002  * Copyright (c) 2008 Nikolaj Hald Nielsen <nhn@kde.org>                                *
0003  * Copyright (c) 2008 Ian Monroe <imonroe@kde.org>                                      *
0004  *                                                                                      *
0005  * This program is free software; you can redistribute it and/or modify it under        *
0006  * the terms of the GNU General Public License as published by the Free Software        *
0007  * Foundation; either version 2 of the License, or (at your option) any later           *
0008  * version.                                                                             *
0009  *                                                                                      *
0010  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0011  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0012  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0013  *                                                                                      *
0014  * You should have received a copy of the GNU General Public License along with         *
0015  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0016  ****************************************************************************************/
0017 
0018 #include "UserPlaylistModel.h"
0019 #include "playlistmanager/PlaylistManager.h"
0020 #include "core/playlists/PlaylistProvider.h"
0021 
0022 #include "AmarokMimeData.h"
0023 #include "core-impl/collections/support/CollectionManager.h"
0024 #include "core/support/Debug.h"
0025 #include "SvgHandler.h"
0026 
0027 #include <QIcon>
0028 
0029 #include <QAbstractListModel>
0030 
0031 #include <typeinfo>
0032 
0033 //Playlist & Track index differentiator macros
0034 //QModelIndex::intenalId() is a qint64 to support 64-bit pointers in a union with the ID
0035 #define TRACK_MASK (0x1<<31)
0036 #define IS_TRACK(x) ((x.internalId()) & (TRACK_MASK))?true:false
0037 #define SET_TRACK_MASK(x) ((x) | (TRACK_MASK))
0038 #define REMOVE_TRACK_MASK(x) ((x) & ~(TRACK_MASK))
0039 
0040 namespace The
0041 {
0042     PlaylistBrowserNS::UserModel* userPlaylistModel()
0043     {
0044         return PlaylistBrowserNS::UserModel::instance();
0045     }
0046 }
0047 
0048 PlaylistBrowserNS::UserModel *PlaylistBrowserNS::UserModel::s_instance = nullptr;
0049 
0050 PlaylistBrowserNS::UserModel *PlaylistBrowserNS::UserModel::instance()
0051 {
0052     if( s_instance == nullptr )
0053         s_instance = new UserModel();
0054 
0055     return s_instance;
0056 }
0057 
0058 void
0059 PlaylistBrowserNS::UserModel::destroy()
0060 {
0061     if( s_instance )
0062     {
0063         delete s_instance;
0064         s_instance = nullptr;
0065     }
0066 }
0067 
0068 PlaylistBrowserNS::UserModel::UserModel()
0069     : PlaylistBrowserModel( PlaylistManager::UserPlaylist )
0070 {
0071     s_instance = this;
0072 }
0073 
0074 PlaylistBrowserNS::UserModel::~UserModel()
0075 {
0076 }
0077 
0078 bool
0079 PlaylistBrowserNS::UserModel::setData( const QModelIndex &idx, const QVariant &value, int role )
0080 {
0081     Q_UNUSED( role )
0082 
0083     switch( idx.column() )
0084     {
0085         case PlaylistBrowserModel::PlaylistItemColumn:
0086         {
0087             QString newName = value.toString().trimmed();
0088             if( newName.isEmpty() )
0089                 return false;
0090             Playlists::PlaylistPtr playlist = m_playlists.value( idx.internalId() );
0091             // we Q_EMIT dataChanged signals later
0092             return The::playlistManager()->rename( playlist, newName );
0093         }
0094         case PlaylistBrowserModel::LabelColumn:
0095         {
0096             debug() << "changing group of item " << idx.internalId() << " to " << value.toString();
0097             Playlists::PlaylistPtr item = m_playlists.value( idx.internalId() );
0098             item->setGroups( value.toStringList() );
0099             // we Q_EMIT dataChanged signals later
0100             return true;
0101         }
0102         default:
0103             return false;
0104     }
0105 
0106     return true;
0107 }
0108 
0109 bool
0110 PlaylistBrowserNS::UserModel::removeRows( int row, int count, const QModelIndex &parent )
0111 {
0112     if( row < 0 || row > rowCount( parent ) )
0113         return false;
0114 
0115     if( !parent.isValid() )
0116     {
0117       Playlists::PlaylistList playlistToRemove;
0118       for( int i = row; i < row + count; i++ )
0119       {
0120         if( m_playlists.count() > i )
0121         {
0122             Playlists::PlaylistPtr playlist = m_playlists[i];
0123             debug() << "Removing " << playlist->name();
0124             playlistToRemove << playlist;
0125         }
0126       }
0127       if( playlistToRemove.isEmpty() )
0128         return false;
0129 
0130       return The::playlistManager()->deletePlaylists( playlistToRemove );
0131     }
0132     int playlistRow = REMOVE_TRACK_MASK(parent.internalId());
0133 
0134     //don't try to get a playlist beyond the last item in the list
0135     if( playlistRow >=  m_playlists.count() )
0136     {
0137         error() << "Tried to remove from non existing playlist:";
0138         error() << playlistRow << " while there are only " << m_playlists.count();
0139         return false;
0140     }
0141 
0142     Playlists::PlaylistPtr playlist = m_playlists.value( playlistRow );
0143 
0144     //if we are trying to delete more tracks then what the playlist has, return.
0145     //count will be at least 1 to delete one track
0146     if( row + count - 1 >= playlist->tracks().count() )
0147     {
0148         error() << "Tried to remove a track using an index that is not there:";
0149         error() << "row: " << row << " count: " << count << " number of tracks: "
0150                 << playlist->tracks().count();
0151         return false;
0152     }
0153 
0154     beginRemoveRows( parent, row, row + count - 1 );
0155     //ignore notifications while removing tracks
0156     unsubscribeFrom( playlist );
0157     for( int i = row; i < row + count; i++ )
0158         //deleting a track moves the next track up, so use the same row number each time
0159         playlist->removeTrack( row );
0160     subscribeTo( playlist );
0161     endRemoveRows();
0162 
0163     return true;
0164 }
0165 
0166 bool
0167 PlaylistBrowserNS::UserModel::dropMimeData ( const QMimeData *data, Qt::DropAction action, int row,
0168         int column, const QModelIndex &parent ) //reimplemented
0169 {
0170     Q_UNUSED( column )
0171 
0172     //let the base class handle the regular actions.
0173     if( PlaylistBrowserModel::dropMimeData( data, action, row, column, parent ) )
0174         return true;
0175 
0176     if( data->hasUrls() )
0177     {
0178         foreach( const QUrl &url, data->urls() )
0179             The::playlistManager()->import( url );
0180     }
0181 
0182     return false;
0183 }
0184