File indexing completed on 2024-05-19 04:49:17
0001 /**************************************************************************************** 0002 * Copyright (c) 2007 Nikolaj Hald Nielsen <nhn@kde.org> * 0003 * Copyright (c) 2007 Maximilian Kossick <maximilian.kossick@googlemail.com> * 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 "MemoryMatcher.h" 0019 0020 using namespace Meta; 0021 0022 MemoryMatcher::MemoryMatcher() 0023 : m_next( nullptr ) 0024 { 0025 } 0026 0027 MemoryMatcher::~MemoryMatcher() 0028 { 0029 delete m_next; 0030 } 0031 0032 bool 0033 MemoryMatcher::isLast() const 0034 { 0035 return !m_next; 0036 } 0037 0038 MemoryMatcher* 0039 MemoryMatcher::next() const 0040 { 0041 return m_next; 0042 } 0043 0044 void 0045 MemoryMatcher::setNext( MemoryMatcher *next ) 0046 { 0047 delete m_next; 0048 m_next = next; 0049 } 0050 0051 TrackMatcher::TrackMatcher( const TrackPtr &track ) 0052 : MemoryMatcher() 0053 , m_track( track ) 0054 {} 0055 0056 TrackList TrackMatcher::match( Collections::MemoryCollection *memColl ) 0057 { 0058 if( !m_track || !memColl ) 0059 return TrackList(); 0060 TrackMap trackMap = memColl->trackMap(); 0061 TrackList result; 0062 if ( trackMap.contains( m_track->uidUrl() ) ) 0063 result.append( trackMap.value( m_track->uidUrl() ) ); 0064 return result; //checking for another matcher is not necessary 0065 } 0066 0067 TrackList TrackMatcher::match( const TrackList &tracks ) 0068 { 0069 if( !m_track ) 0070 return TrackList(); 0071 TrackList result; 0072 QString url = m_track->uidUrl(); 0073 foreach( TrackPtr track, tracks ) 0074 if ( track->uidUrl() == url ) 0075 { 0076 result.append( track ); 0077 break; 0078 } 0079 return result; //checking for another matcher is not necessary 0080 } 0081 0082 0083 0084 ArtistMatcher::ArtistMatcher( const ArtistPtr &artist, Collections::QueryMaker::ArtistMatchBehaviour artistMode ) 0085 : MemoryMatcher() 0086 , m_artist( artist ) 0087 , m_queryMode( artistMode ) 0088 {} 0089 0090 TrackList ArtistMatcher::match( Collections::MemoryCollection *memColl ) 0091 { 0092 if( !m_artist || !memColl ) 0093 return TrackList(); 0094 0095 if( !memColl->artistMap().contains( m_artist->name() ) ) 0096 return TrackList(); 0097 0098 ArtistPtr artist = memColl->artistMap().value( m_artist->name() ); 0099 0100 TrackList matchingTracks; 0101 switch( m_queryMode ) 0102 { 0103 case Collections::QueryMaker::AlbumOrTrackArtists: 0104 case Collections::QueryMaker::AlbumArtists: 0105 foreach( AlbumPtr album, memColl->albumMap() ) 0106 if( album->albumArtist() == artist ) 0107 matchingTracks.append( album->tracks() ); 0108 if( m_queryMode != Collections::QueryMaker::AlbumOrTrackArtists ) 0109 break; 0110 Q_FALLTHROUGH(); 0111 case Collections::QueryMaker::TrackArtists: 0112 matchingTracks.append( artist->tracks() ); 0113 } 0114 0115 if( isLast() || matchingTracks.isEmpty() ) 0116 return matchingTracks; 0117 else 0118 return next()->match( matchingTracks ); 0119 } 0120 0121 0122 TrackList ArtistMatcher::match( const TrackList &tracks ) 0123 { 0124 if( !m_artist ) 0125 return TrackList(); 0126 TrackList matchingTracks; 0127 QString name = m_artist->name(); 0128 foreach( TrackPtr track, tracks ) 0129 switch( m_queryMode ) 0130 { 0131 case Collections::QueryMaker::AlbumOrTrackArtists: 0132 case Collections::QueryMaker::AlbumArtists: 0133 if( track->album()->hasAlbumArtist() && 0134 track->album()->albumArtist()->name() == name ) 0135 matchingTracks.append( track ); 0136 if( m_queryMode != Collections::QueryMaker::AlbumOrTrackArtists ) 0137 break; 0138 Q_FALLTHROUGH(); 0139 case Collections::QueryMaker::TrackArtists: 0140 if( track->artist()->name() == name ) 0141 matchingTracks.append( track ); 0142 } 0143 0144 if( isLast() || matchingTracks.isEmpty() ) 0145 return matchingTracks; 0146 else 0147 return next()->match( matchingTracks ); 0148 } 0149 0150 0151 0152 AlbumMatcher::AlbumMatcher( const AlbumPtr &album ) 0153 : MemoryMatcher() 0154 , m_album( album ) 0155 {} 0156 0157 TrackList AlbumMatcher::match( Collections::MemoryCollection *memColl ) 0158 { 0159 if( !m_album || !memColl ) 0160 return TrackList(); 0161 AlbumMap albumMap = memColl->albumMap(); 0162 if ( albumMap.contains( m_album ) ) // compares albums by value 0163 { 0164 AlbumPtr album = albumMap.value( m_album ); // compares albums by value, too 0165 TrackList matchingTracks = album->tracks(); 0166 if ( isLast() ) 0167 return matchingTracks; 0168 else 0169 return next()->match( matchingTracks ); 0170 } 0171 else 0172 return TrackList(); 0173 } 0174 0175 TrackList AlbumMatcher::match( const TrackList &tracks ) 0176 { 0177 if( !m_album ) 0178 return TrackList(); 0179 TrackList matchingTracks; 0180 QString name = m_album->name(); 0181 foreach( TrackPtr track, tracks ) 0182 if ( track->album()->name() == name ) 0183 matchingTracks.append( track ); 0184 if ( isLast() || matchingTracks.isEmpty()) 0185 return matchingTracks; 0186 else 0187 return next()->match( matchingTracks ); 0188 } 0189 0190 0191 0192 GenreMatcher::GenreMatcher( const GenrePtr &genre ) 0193 : MemoryMatcher() 0194 , m_genre( genre ) 0195 {} 0196 0197 TrackList GenreMatcher::match( Collections::MemoryCollection *memColl ) 0198 { 0199 if( !m_genre || !memColl ) 0200 return TrackList(); 0201 GenreMap genreMap = memColl->genreMap(); 0202 if ( genreMap.contains( m_genre->name() ) ) 0203 { 0204 GenrePtr genre = genreMap.value( m_genre->name() ); 0205 TrackList matchingTracks = genre->tracks(); 0206 if ( isLast() ) 0207 return matchingTracks; 0208 else 0209 return next()->match( matchingTracks ); 0210 } 0211 else 0212 return TrackList(); 0213 } 0214 0215 TrackList GenreMatcher::match( const TrackList &tracks ) 0216 { 0217 if( !m_genre ) 0218 return TrackList(); 0219 TrackList matchingTracks; 0220 QString name = m_genre->name(); 0221 foreach( TrackPtr track, tracks ) 0222 if ( track->genre()->name() == name ) 0223 matchingTracks.append( track ); 0224 if ( isLast() || matchingTracks.isEmpty()) 0225 return matchingTracks; 0226 else 0227 return next()->match( matchingTracks ); 0228 } 0229 0230 0231 0232 ComposerMatcher::ComposerMatcher( const ComposerPtr &composer ) 0233 : MemoryMatcher() 0234 , m_composer( composer ) 0235 {} 0236 0237 TrackList ComposerMatcher::match( Collections::MemoryCollection *memColl ) 0238 { 0239 if( !m_composer || !memColl ) 0240 return TrackList(); 0241 ComposerMap composerMap = memColl->composerMap(); 0242 if ( composerMap.contains( m_composer->name() ) ) 0243 { 0244 ComposerPtr composer = composerMap.value( m_composer->name() ); 0245 TrackList matchingTracks = composer->tracks(); 0246 if ( isLast() ) 0247 return matchingTracks; 0248 else 0249 return next()->match( matchingTracks ); 0250 } 0251 else 0252 return TrackList(); 0253 } 0254 0255 TrackList ComposerMatcher::match( const TrackList &tracks ) 0256 { 0257 if( !m_composer ) 0258 return TrackList(); 0259 TrackList matchingTracks; 0260 QString name = m_composer->name(); 0261 foreach( TrackPtr track, tracks ) 0262 if ( track->composer()->name() == name ) 0263 matchingTracks.append( track ); 0264 if ( isLast() || matchingTracks.isEmpty()) 0265 return matchingTracks; 0266 else 0267 return next()->match( matchingTracks ); 0268 } 0269 0270 0271 0272 YearMatcher::YearMatcher( const YearPtr &year ) 0273 : MemoryMatcher() 0274 , m_year( year ) 0275 {} 0276 0277 TrackList YearMatcher::match( Collections::MemoryCollection *memColl ) 0278 { 0279 if( !m_year || !memColl ) 0280 return TrackList(); 0281 YearMap yearMap = memColl->yearMap(); 0282 if ( yearMap.contains( m_year->year() ) ) 0283 { 0284 YearPtr year = yearMap.value( m_year->year() ); 0285 TrackList matchingTracks = year->tracks(); 0286 if ( isLast() ) 0287 return matchingTracks; 0288 else 0289 return next()->match( matchingTracks ); 0290 } 0291 else 0292 return TrackList(); 0293 } 0294 0295 TrackList YearMatcher::match( const TrackList &tracks ) 0296 { 0297 if( !m_year ) 0298 return TrackList(); 0299 TrackList matchingTracks; 0300 int year = m_year->year(); 0301 foreach( TrackPtr track, tracks ) 0302 if ( track->year()->year() == year ) 0303 matchingTracks.append( track ); 0304 if ( isLast() || matchingTracks.isEmpty()) 0305 return matchingTracks; 0306 else 0307 return next()->match( matchingTracks ); 0308 } 0309 0310 LabelMatcher::LabelMatcher( const Meta::LabelPtr &label ) 0311 : MemoryMatcher() 0312 , m_label( label ) 0313 { 0314 //nothing to do 0315 } 0316 0317 Meta::TrackList 0318 LabelMatcher::match( const Meta::TrackList &tracks ) 0319 { 0320 if( !m_label ) 0321 return Meta::TrackList(); 0322 0323 Meta::TrackList matchingTracks; 0324 QString name = m_label->name(); 0325 //not really efficient... 0326 foreach( const Meta::TrackPtr &track, tracks ) 0327 { 0328 foreach( const Meta::LabelPtr &label, track->labels() ) 0329 { 0330 if( name == label->name() ) 0331 { 0332 matchingTracks << track; 0333 break; 0334 } 0335 } 0336 } 0337 if( isLast() || matchingTracks.isEmpty() ) 0338 return matchingTracks; 0339 else 0340 return next()->match( matchingTracks ); 0341 } 0342 0343 Meta::TrackList 0344 LabelMatcher::match( Collections::MemoryCollection *memColl ) 0345 { 0346 if( !m_label ) 0347 return Meta::TrackList(); 0348 0349 Meta::TrackList matchingTracks; 0350 0351 if( memColl->labelMap().contains( m_label->name() ) ) 0352 { 0353 //m_label might actually be a proxy label 0354 Meta::LabelPtr realLabel = memColl->labelMap().value( m_label->name() ); 0355 matchingTracks = memColl->labelToTrackMap().value( realLabel ); 0356 } 0357 if( isLast() || matchingTracks.isEmpty() ) 0358 return matchingTracks; 0359 else 0360 return next()->match( matchingTracks ); 0361 } 0362 0363 0364 0365 0366