double ConstraintTypes::TagMatch::satisfaction( const Meta::TrackList& tl ) const { double satisfaction = 0.0; foreach( Meta::TrackPtr t, tl ) { if ( matches( t ) ) { satisfaction += 1.0; } } satisfaction /= ( double )tl.size(); return satisfaction; }
void APG::ConstraintSolver::mutate_population( APG::ConstraintSolver::Population& population ) { if ( population.size() < 1 ) return; const double mutantPercentage = 0.35; // TODO: tune this parameter QList<Meta::TrackList*> parents( population.keys() ); int maxMutants = (int)( mutantPercentage * (double)(m_populationSize) ); for ( int i = parents.size(); i < maxMutants; i++ ) { int idx = KRandom::random() % parents.size(); Meta::TrackList* child = new Meta::TrackList( *(parents.at( idx )) ); int op = KRandom::random() % 5; int s = child->size(); switch (op) { case 0: child->removeAt( KRandom::random() % s ); case 1: child->insert( KRandom::random() % ( s + 1 ), random_track_from_domain() ); case 2: child->replace( KRandom::random() % s, random_track_from_domain() ); case 3: child->swap( KRandom::random() % s, KRandom::random() % s ); case 4: child = crossover( child, parents.at( KRandom::random() % parents.size() ) ); default: (void)0; // effectively a no-op. the default is here so that the compiler doesn't complain about missing default in switch } population.insert( child, m_constraintTreeRoot->satisfaction( *child ) ); } return; }
Dynamic::TrackSet Dynamic::AlbumPlayBias::matchingTracks( int position, const Meta::TrackList& playlist, int contextCount, Dynamic::TrackCollectionPtr universe ) const { Q_UNUSED( contextCount ); if( position < 1 || position >= playlist.count() ) return Dynamic::TrackSet( universe, false ); Meta::TrackPtr track = playlist[position-1]; Meta::AlbumPtr album = track->album(); if( !album ) return Dynamic::TrackSet( universe, false ); Meta::TrackList albumTracks = album->tracks(); if( albumTracks.count() == 1 || (track == albumTracks.last() && m_follow != DontCare) ) return Dynamic::TrackSet( universe, false ); // we assume that the album tracks are sorted by cd and track number which // is at least true for the SqlCollection TrackSet result( universe, false ); if( m_follow == DirectlyFollow ) { for( int i = 1; i < albumTracks.count(); i++ ) if( albumTracks[i-1] == track ) result.unite( albumTracks[i] ); } else if( m_follow == Follow ) { bool found = false; for( int i = 0; i < albumTracks.count(); i++ ) { if( found ) result.unite( albumTracks[i] ); if( albumTracks[i] == track ) found = true; } } else if( m_follow == DontCare ) { for( int i = 0; i < albumTracks.count(); i++ ) { if( albumTracks[i] != track ) result.unite( albumTracks[i] ); } } return result; }
bool Dynamic::LastFmBias::trackMatches( int position, const Meta::TrackList& playlist, int contextCount ) const { Q_UNUSED( contextCount ); if( position <= 0 || position >= playlist.count()) return false; // determine the last track and artist Meta::TrackPtr lastTrack = playlist[position-1]; Meta::ArtistPtr lastArtist = lastTrack->artist(); QString lastTrackName = lastTrack->name(); QString lastArtistName = lastArtist ? lastArtist->name() : QString(); Meta::TrackPtr currentTrack = playlist[position-1]; Meta::ArtistPtr currentArtist = currentTrack->artist(); QString currentTrackName = currentTrack->name(); QString currentArtistName = currentArtist ? currentArtist->name() : QString(); { QMutexLocker locker( &m_mutex ); if( m_match == SimilarArtist ) { if( lastArtistName.isEmpty() ) return true; if( currentArtistName.isEmpty() ) return false; if( m_similarArtistMap.contains( lastArtistName ) ) return m_similarArtistMap.value( lastArtistName ).contains( currentArtistName ); } else if( m_match == SimilarTrack ) { if( lastTrackName.isEmpty() ) return true; if( currentTrackName.isEmpty() ) return false; TitleArtistPair lastKey( lastTrackName, lastArtistName ); TitleArtistPair currentKey( currentTrackName, currentArtistName ); if( m_similarTrackMap.contains( lastKey ) ) return m_similarTrackMap.value( lastKey ).contains( currentKey ); } } warning() << "didn't have a cached suggestions for track:" << lastTrackName; return false; }
double ConstraintTypes::PlaylistLength::satisfaction( const Meta::TrackList& tl ) const { quint32 l = static_cast<quint32>( tl.size() ); if ( m_comparison == CompareNumEquals ) { if ( l > m_length ) return ( l == m_length ) ? 1.0 : transformLength( l - m_length ); else return ( l == m_length ) ? 1.0 : transformLength( m_length - l ); } else if ( m_comparison == CompareNumGreaterThan ) { return ( l > m_length ) ? 1.0 : transformLength( m_length - l ); } else if ( m_comparison == CompareNumLessThan ) { return ( l < m_length ) ? 1.0 : transformLength( l - m_length ); } else { return 0.0; } }
bool Dynamic::WeeklyTopBias::trackMatches( int position, const Meta::TrackList& playlist, int contextCount ) const { Q_UNUSED( contextCount ); if( position < 0 || position >= playlist.count()) return false; // - determine the current artist Meta::TrackPtr currentTrack = playlist[position-1]; Meta::ArtistPtr currentArtist = currentTrack->artist(); QString currentArtistName = currentArtist ? currentArtist->name() : QString(); // - collect all the artists QStringList artists; bool weeksMissing = false; uint fromTime = m_range.from.toTime_t(); uint toTime = m_range.to.toTime_t(); uint lastWeekTime = 0; foreach( uint weekTime, m_weeklyFromTimes ) { if( weekTime > fromTime && weekTime < toTime && lastWeekTime ) { if( m_weeklyArtistMap.contains( lastWeekTime ) ) { artists.append( m_weeklyArtistMap.value( lastWeekTime ) ); // debug() << "found already-saved data for week:" << lastWeekTime << m_weeklyArtistMap.value( lastWeekTime ); } else { weeksMissing = true; } } lastWeekTime = weekTime; } if( weeksMissing ) warning() << "didn't have a cached suggestions for weeks:" << m_range.from << "to" << m_range.to; return artists.contains( currentArtistName ); }
Dynamic::TrackSet Dynamic::LastFmBias::matchingTracks( int position, const Meta::TrackList& playlist, int contextCount, Dynamic::TrackCollectionPtr universe ) const { Q_UNUSED( contextCount ); if( position <= 0 || position > playlist.count()) return Dynamic::TrackSet( universe, true ); // determine the last track and artist Meta::TrackPtr lastTrack = playlist[position-1]; Meta::ArtistPtr lastArtist = lastTrack->artist(); m_currentTrack = lastTrack->name(); m_currentArtist = lastArtist ? lastArtist->name() : QString(); { QMutexLocker locker( &m_mutex ); if( m_match == SimilarArtist ) { if( m_currentArtist.isEmpty() ) return Dynamic::TrackSet( universe, true ); if( m_tracksValid && m_tracksMap.contains( m_currentArtist ) ) return m_tracksMap.value( m_currentArtist ); } else if( m_match == SimilarTrack ) { if( m_currentTrack.isEmpty() ) return Dynamic::TrackSet( universe, true ); QString key = m_currentTrack + '|' + m_currentArtist; if( m_tracksValid && m_tracksMap.contains( key ) ) return m_tracksMap.value( key ); } } m_tracks = Dynamic::TrackSet( universe, false ); QTimer::singleShot(0, const_cast<LastFmBias*>(this), SLOT(newQuery())); // create the new query from my parent thread return Dynamic::TrackSet(); }
bool Dynamic::QuizPlayBias::trackMatches( int position, const Meta::TrackList& playlist, int contextCount ) const { Q_UNUSED( contextCount ); if( position <= 0 || position >= playlist.count()) return true; // -- determine the last character we need to quiz Meta::TrackPtr lastTrack = playlist[position-1]; Meta::DataPtr lastData; if( m_follow == TitleToTitle ) lastData = Meta::DataPtr::staticCast<Meta::Track>(lastTrack); else if( m_follow == ArtistToArtist ) lastData = Meta::DataPtr::staticCast<Meta::Artist>(lastTrack->artist()); else if( m_follow == AlbumToAlbum ) lastData = Meta::DataPtr::staticCast<Meta::Album>(lastTrack->album()); if( !lastData || lastData->name().isEmpty() ) return true; // -- determine the first character Meta::TrackPtr track = playlist[position]; Meta::DataPtr data; if( m_follow == TitleToTitle ) data = Meta::DataPtr::staticCast<Meta::Track>(track); else if( m_follow == ArtistToArtist ) data = Meta::DataPtr::staticCast<Meta::Artist>(track->artist()); else if( m_follow == AlbumToAlbum ) data = Meta::DataPtr::staticCast<Meta::Album>(track->album()); if( !data || data->name().isEmpty() ) return false; // -- now compare QString lastName = lastData->name(); QString name = data->name(); return lastChar( lastName ).toLower() == name[0].toLower(); }
Dynamic::TrackSet Dynamic::QuizPlayBias::matchingTracks( int position, const Meta::TrackList& playlist, int contextCount, Dynamic::TrackCollectionPtr universe ) const { Q_UNUSED( contextCount ); if( position <= 0 || position > playlist.count()) return Dynamic::TrackSet( universe, true ); // determine the last character we need to quiz Meta::TrackPtr lastTrack = playlist[position-1]; Meta::DataPtr lastData; if( m_follow == TitleToTitle ) lastData = Meta::DataPtr::staticCast<Meta::Track>(lastTrack); else if( m_follow == ArtistToArtist ) lastData = Meta::DataPtr::staticCast<Meta::Artist>(lastTrack->artist()); else if( m_follow == AlbumToAlbum ) lastData = Meta::DataPtr::staticCast<Meta::Album>(lastTrack->album()); if( !lastData || lastData->name().isEmpty() ) { // debug() << "QuizPlay: no data for"<<lastTrack->name(); return Dynamic::TrackSet( universe, true ); } m_currentCharacter = lastChar(lastData->name()).toLower(); // debug() << "QuizPlay: data for"<<lastTrack->name()<<"is"<<m_currentCharacter; // -- look if we already buffered it if( m_tracksValid && m_characterTrackMap.contains( m_currentCharacter ) ) return m_characterTrackMap.value( m_currentCharacter ); // -- start a new query m_tracks = Dynamic::TrackSet( universe, false ); QTimer::singleShot(0, const_cast<QuizPlayBias*>(this), SLOT(newQuery())); // create the new query from my parent thread return Dynamic::TrackSet(); }
OrganizeCollectionDialog::OrganizeCollectionDialog( const Meta::TrackList &tracks, const QStringList &folders, const QString &targetExtension, QWidget *parent, const char *name, bool modal, const QString &caption, QFlags<KDialog::ButtonCode> buttonMask ) : KDialog( parent ) , ui( new Ui::OrganizeCollectionDialogBase ) , m_detailed( true ) , m_schemeModified( false ) , m_conflict( false ) { Q_UNUSED( name ) setCaption( caption ); setModal( modal ); setButtons( buttonMask ); showButtonSeparator( true ); m_targetFileExtension = targetExtension; if( tracks.size() > 0 ) m_allTracks = tracks; KVBox *mainVBox = new KVBox( this ); setMainWidget( mainVBox ); QWidget *mainContainer = new QWidget( mainVBox ); ui->setupUi( mainContainer ); m_trackOrganizer = new TrackOrganizer( m_allTracks, this ); ui->folderCombo->insertItems( 0, folders ); if( ui->folderCombo->contains( AmarokConfig::organizeDirectory() ) ) ui->folderCombo->setCurrentItem( AmarokConfig::organizeDirectory() ); else ui->folderCombo->setCurrentIndex( 0 ); //TODO possible bug: assumes folder list is not empty. ui->overwriteCheck->setChecked( AmarokConfig::overwriteFiles() ); ui->optionsWidget->setReplaceSpaces( AmarokConfig::replaceSpace() ); ui->optionsWidget->setPostfixThe( AmarokConfig::ignoreThe() ); ui->optionsWidget->setVfatCompatible( AmarokConfig::vfatCompatible() ); ui->optionsWidget->setAsciiOnly( AmarokConfig::asciiOnly() ); ui->optionsWidget->setRegexpText( AmarokConfig::replacementRegexp() ); ui->optionsWidget->setReplaceText( AmarokConfig::replacementString() ); ui->previewTableWidget->horizontalHeader()->setResizeMode( QHeaderView::ResizeToContents ); ui->conflictLabel->setText(""); QPalette p = ui->conflictLabel->palette(); KColorScheme::adjustForeground( p, KColorScheme::NegativeText ); // TODO this isn't working, the color is still normal ui->conflictLabel->setPalette( p ); ui->previewTableWidget->sortItems( 0, Qt::AscendingOrder ); // only show the options when the Options button is checked connect( ui->optionsButton, SIGNAL(toggled(bool)), ui->organizeCollectionWidget, SLOT(setVisible(bool)) ); connect( ui->optionsButton, SIGNAL(toggled(bool)), ui->optionsWidget, SLOT(setVisible(bool)) ); ui->organizeCollectionWidget->hide(); ui->optionsWidget->hide(); connect( ui->folderCombo, SIGNAL(currentIndexChanged(QString)), SLOT(slotUpdatePreview()) ); connect( ui->organizeCollectionWidget, SIGNAL(schemeChanged()), SLOT(slotUpdatePreview()) ); connect( ui->optionsWidget, SIGNAL(optionsChanged()), SLOT(slotUpdatePreview())); // to show the conflict error connect( ui->overwriteCheck, SIGNAL(stateChanged(int)), SLOT(slotOverwriteModeChanged()) ); connect( this, SIGNAL(finished(int)), ui->organizeCollectionWidget, SLOT(slotSaveFormatList()) ); connect( this, SIGNAL(accepted()), ui->organizeCollectionWidget, SLOT(onAccept()) ); connect( this, SIGNAL(accepted()), SLOT(slotDialogAccepted()) ); connect( ui->folderCombo, SIGNAL(currentIndexChanged(QString)), SLOT(slotEnableOk(QString)) ); slotEnableOk( ui->folderCombo->currentText() ); restoreDialogSize( Amarok::config( "OrganizeCollectionDialog" ) ); QTimer::singleShot( 0, this, SLOT(slotUpdatePreview()) ); }
Meta::TrackList APG::ConstraintSolver::sample( Meta::TrackList domain, const int sampleSize ) const { std::random_shuffle( domain.begin(), domain.end() ); return domain.mid( 0, sampleSize ); }
void Albums::dataUpdated( const QString &name, const Plasma::DataEngine::Data &data ) { if( name != QLatin1String("albums") ) return; Meta::AlbumList albums = data[ "albums" ].value<Meta::AlbumList>(); Meta::TrackPtr track = data[ "currentTrack" ].value<Meta::TrackPtr>(); QString headerText = data[ "headerText" ].toString(); setHeaderText( headerText.isEmpty() ? i18n("Albums") : headerText ); //Don't keep showing the albums for the artist of the last track that had album in the collection if( (m_currentTrack == track) && (m_albums == albums) ) return; if( albums.isEmpty() ) { debug() << "received albums is empty"; setCollapseOn(); m_albums.clear(); m_albumsView->clear(); return; } setCollapseOff(); m_albums = albums; m_currentTrack = track; m_albumsView->clear(); m_albumsView->setMode( track ? AlbumsProxyModel::SortByYear : AlbumsProxyModel::SortByCreateDate ); QStandardItem *currentItem( 0 ); foreach( Meta::AlbumPtr albumPtr, albums ) { // do not show all tracks without an album from the collection, this takes ages // TODO: show all tracks from this artist that are not part of an album if( albumPtr->name().isEmpty() ) continue; Meta::TrackList tracks = albumPtr->tracks(); if( tracks.isEmpty() ) continue; AlbumItem *albumItem = new AlbumItem(); albumItem->setIconSize( 50 ); albumItem->setAlbum( albumPtr ); albumItem->setShowArtist( !m_currentTrack ); int numberOfDiscs = 0; int childRow = 0; qStableSort( tracks.begin(), tracks.end(), Meta::Track::lessThan ); QMultiHash< int, TrackItem* > trackItems; // hash of tracks items for each disc foreach( Meta::TrackPtr trackPtr, tracks ) { if( numberOfDiscs < trackPtr->discNumber() ) numberOfDiscs = trackPtr->discNumber(); TrackItem *trackItem = new TrackItem(); trackItem->setTrack( trackPtr ); // bold the current track to make it more visible if( m_currentTrack && *m_currentTrack == *trackPtr ) { currentItem = trackItem; trackItem->bold(); } // If compilation and same artist, then highlight, but only if there's a current track if( m_currentTrack && m_currentTrack->artist() && trackPtr->artist() && (*m_currentTrack->artist() == *trackPtr->artist()) && albumPtr->isCompilation() ) { trackItem->italicise(); } trackItems.insert( trackPtr->discNumber(), trackItem ); } for( int i = 0; i <= numberOfDiscs; ++i ) { QList<TrackItem*> items = trackItems.values( i ); if( !items.isEmpty() ) { const TrackItem *item = items.first(); QStandardItem *discItem( 0 ); if( numberOfDiscs > 1 ) { discItem = new QStandardItem( i18n("Disc %1", item->track()->discNumber()) ); albumItem->setChild( childRow++, discItem ); int discChildRow = 0; foreach( TrackItem *trackItem, items ) discItem->setChild( discChildRow++, trackItem ); } else { foreach( TrackItem *trackItem, items ) albumItem->setChild( childRow++, trackItem ); } } } m_albumsView->appendAlbum( albumItem ); } m_albumsView->sort(); if( currentItem ) { m_albumsView->setRecursiveExpanded( currentItem, true ); m_albumsView->scrollTo( currentItem ); } updateConstraints(); }