File indexing completed on 2024-05-05 04:48:30

0001 /****************************************************************************************
0002  * Copyright (c) 2008 Daniel Caleb Jones <danielcjones@gmail.com>                       *
0003  *                                                                                      *
0004  * This program is free software; you can redistribute it and/or modify it under        *
0005  * the terms of the GNU General Public License as published by the Free Software        *
0006  * Foundation; either version 2 of the License, or (at your option) version 3 or        *
0007  * any later version accepted by the membership of KDE e.V. (or its successor approved  *
0008  * by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of  *
0009  * version 3 of the license.                                                            *
0010  *                                                                                      *
0011  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0012  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0013  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0014  *                                                                                      *
0015  * You should have received a copy of the GNU General Public License along with         *
0016  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0017  ****************************************************************************************/
0018 
0019 #include "TrackSet.h"
0020 
0021 #include "core/collections/Collection.h"
0022 #include "core/meta/Meta.h"
0023 #include "core/support/Debug.h"
0024 
0025 #include <QRandomGenerator>
0026 
0027 Dynamic::TrackCollection::TrackCollection( const QStringList& uids )
0028 {
0029     m_uids = uids;
0030     for( int i = 0; i < m_uids.count(); i++ )
0031         m_ids.insert( m_uids[i], i );
0032 }
0033 
0034 int
0035 Dynamic::TrackCollection::count() const
0036 {
0037     return m_uids.count();
0038 }
0039 
0040 QStringList
0041 Dynamic::TrackCollection::uids() const
0042 {
0043     return m_uids;
0044 }
0045 
0046 Dynamic::TrackSet::TrackSet()
0047     : m_bits()
0048     , m_collection( nullptr )
0049 { }
0050 
0051 Dynamic::TrackSet::TrackSet( const TrackSet& other )
0052     : m_bits( other.m_bits )
0053     , m_collection( other.m_collection )
0054 { }
0055 
0056 Dynamic::TrackSet::TrackSet( const Dynamic::TrackCollectionPtr &collection, bool value )
0057     : m_bits( collection->count(), value )
0058     , m_collection( collection )
0059 {}
0060 
0061 void
0062 Dynamic::TrackSet::reset( bool value )
0063 {
0064     m_bits.fill( value );
0065 }
0066 
0067 bool
0068 Dynamic::TrackSet::isOutstanding() const
0069 {
0070     return !m_collection;
0071 }
0072 
0073 int
0074 Dynamic::TrackSet::trackCount() const
0075 {
0076     return m_bits.count(true);
0077 }
0078 
0079 bool
0080 Dynamic::TrackSet::isEmpty() const
0081 {
0082     return m_bits.count(false) == m_bits.count();
0083 }
0084 
0085 bool
0086 Dynamic::TrackSet::isFull() const
0087 {
0088     return m_bits.count(true) == m_bits.count();
0089 }
0090 
0091 bool
0092 Dynamic::TrackSet::contains( const QString &uid ) const
0093 {
0094     if( !m_collection )
0095         return false;
0096 
0097     if( !m_collection->m_ids.contains( uid ) )
0098         return false;
0099 
0100     int index = m_collection->m_ids.value( uid );
0101     return m_bits.at( index );
0102 }
0103 
0104 bool
0105 Dynamic::TrackSet::contains( const Meta::TrackPtr& B ) const
0106 {
0107     if( !m_collection )
0108         return false;
0109     if( !B )
0110         return false;
0111 
0112     QString str = B->uidUrl();
0113     if( !m_collection->m_ids.contains( str ) )
0114         return false;
0115 
0116     int index = m_collection->m_ids.value( str );
0117     return m_bits.at( index );
0118 }
0119 
0120 QString
0121 Dynamic::TrackSet::getRandomTrack() const
0122 {
0123     if( !m_collection )
0124         return QString();
0125 
0126     int count = trackCount();
0127     if( count == 0 )
0128         return QString();
0129 
0130     // stupid that I have to go through the set like this...
0131     int trackNr = QRandomGenerator::global()->generate() % count;
0132     for( int i = m_bits.size()-1; i>=0; i-- )
0133     {
0134         if( m_bits.at(i) )
0135         {
0136             if( trackNr )
0137                 trackNr--;
0138             else
0139             {
0140                 return m_collection->m_uids.at(i);
0141             }
0142         }
0143     }
0144 
0145     return QString();
0146 }
0147 
0148 void
0149 Dynamic::TrackSet::unite( const Meta::TrackPtr& B )
0150 {
0151     if( !m_collection )
0152         return;
0153     if( !B )
0154         return;
0155 
0156     QString str = B->uidUrl();
0157     if( !m_collection->m_ids.contains( str ) ) {
0158         warning() << "TrackSet::subtract called for a track not even known to the collection. Track uid is"<<str<<"example from collection"<<m_collection->m_ids.keys().first();
0159         return;
0160     }
0161 
0162     int index = m_collection->m_ids.value( str );
0163     m_bits.setBit( index );
0164 }
0165 
0166 void
0167 Dynamic::TrackSet::unite( const Dynamic::TrackSet& B )
0168 {
0169     m_bits |= B.m_bits;
0170 }
0171 
0172 void
0173 Dynamic::TrackSet::unite( const QStringList& B )
0174 {
0175     if( !m_collection )
0176         return;
0177 
0178     foreach( const QString &str, B )
0179     {
0180         if( !m_collection->m_ids.contains( str ) )
0181             continue;
0182 
0183         int index = m_collection->m_ids.value( str );
0184         m_bits.setBit( index );
0185     }
0186 }
0187 
0188 void
0189 Dynamic::TrackSet::intersect( const Dynamic::TrackSet& B )
0190 {
0191     m_bits &= B.m_bits;
0192 }
0193 
0194 void
0195 Dynamic::TrackSet::intersect( const QStringList& B )
0196 {
0197     if( !m_collection )
0198         return;
0199 
0200     QBitArray bBits( m_bits.count() );
0201     foreach( const QString &str, B )
0202     {
0203         if( !m_collection->m_ids.contains( str ) )
0204             continue;
0205 
0206         int index = m_collection->m_ids.value( str );
0207         bBits.setBit( index );
0208     }
0209 
0210     m_bits &= bBits;
0211 }
0212 
0213 void
0214 Dynamic::TrackSet::subtract( const Meta::TrackPtr& B )
0215 {
0216     if( !m_collection )
0217         return;
0218     if( !B )
0219         return;
0220 
0221     QString str = B->uidUrl();
0222     if( !m_collection->m_ids.contains( str ) )
0223     {
0224         // that seems to happen. e.g. for tracks from the file collection
0225         warning() << "TrackSet::subtract called for a track not even known to the collection. "<<
0226             "Track uid is"<<str<<
0227             "example from collection"<<(m_collection->m_ids.isEmpty()?QStringLiteral("no example"):QString(m_collection->m_ids.keys().first()))<<
0228             "track is from collection"<<(B->collection()?B->collection()->collectionId():QStringLiteral("no collection"));
0229         return;
0230     }
0231 
0232     int index = m_collection->m_ids.value( str );
0233     m_bits.clearBit( index );
0234 }
0235 
0236 void
0237 Dynamic::TrackSet::subtract( const Dynamic::TrackSet& B )
0238 {
0239     m_bits |= B.m_bits;
0240     m_bits ^= B.m_bits;
0241 }
0242 
0243 void
0244 Dynamic::TrackSet::subtract( const QStringList& B )
0245 {
0246     if( !m_collection )
0247         return;
0248 
0249     foreach( const QString &str, B )
0250     {
0251         if( !m_collection->m_ids.contains( str ) )
0252             continue;
0253 
0254         int index = m_collection->m_ids.value( str );
0255         m_bits.clearBit( index );
0256     }
0257 }
0258 
0259 
0260 
0261 
0262 Dynamic::TrackSet&
0263 Dynamic::TrackSet::operator=( const Dynamic::TrackSet& B )
0264 {
0265     m_bits = B.m_bits;
0266     m_collection = B.m_collection;
0267     return *this;
0268 }
0269 
0270 
0271