metabundle.cpp
来自「Amarok是一款在LINUX或其他类UNIX操作系统中运行的音频播放器软件。 」· C++ 代码 · 共 1,884 行 · 第 1/5 页
CPP
1,884 行
case Bitrate: setBitrate( newText.toInt() ); break; case SampleRate: setSampleRate( newText.toInt() ); break; case Score: setScore( newText.toFloat() ); break; case Rating: setRating( newText.toInt() ); break; case PlayCount: setPlayCount( newText.toInt() ); break; case LastPlayed: setLastPlay( newText.toInt() ); break; case Filesize: setFilesize( newText.toInt() ); break; case Type: setFileType( newText.toInt() ); break; default: warning() << "Tried to set the text of an immutable or nonexistent column! [" << column << endl; }}QString MetaBundle::exactText( int column, bool ensureCached ) const{ switch( column ) { case Filename: return filename(); case Title: return title(); case Artist: return artist(); case AlbumArtist: return albumArtist(); case Composer: return composer(); case Year: return QString::number( year() ); case Album: return album(); case DiscNumber: return QString::number( discNumber() ); case Track: return QString::number( track() ); case Bpm: return QString::number( bpm() ); case Genre: return genre(); case Comment: return comment(); case Directory: return directory(); case Type: return QString::number( fileType() ); case Length: return QString::number( length() ); case Bitrate: return QString::number( bitrate() ); case SampleRate: return QString::number( sampleRate() ); case Score: return QString::number( score( ensureCached ) ); case Rating: return QString::number( rating( ensureCached ) ); case PlayCount: return QString::number( playCount( ensureCached ) ); case LastPlayed: return QString::number( lastPlay( ensureCached ) ); case Filesize: return QString::number( filesize() ); case Mood: return QString(); default: warning() << "Tried to get the text of a nonexistent column! [" << column << endl; } return QString(); //shouldn't happen}QString MetaBundle::prettyText( int column ) const{ QString text; switch( column ) { case Filename: text = isFile() ? MetaBundle::prettyTitle(filename()) : url().prettyURL(); break; case Title: text = title().isEmpty() ? MetaBundle::prettyTitle( filename() ) : title(); break; case Artist: text = artist(); break; case AlbumArtist: text = albumArtist(); break; case Composer: text = composer(); break; case Year: text = year() ? QString::number( year() ) : QString::null; break; case Album: text = album(); break; case DiscNumber: text = discNumber() ? QString::number( discNumber() ) : QString::null; break; case Bpm: text = bpm() ? QString::number( bpm() ) : QString::null; break; case Track: text = track() ? QString::number( track() ) : QString::null; break; case Genre: text = genre(); break; case Comment: text = comment(); break; case Directory: text = url().isEmpty() ? QString() : directory(); break; case Type: text = url().isEmpty() ? QString() : type(); break; case Length: text = prettyLength( length(), true ); break; case Bitrate: text = prettyBitrate( bitrate() ); break; case SampleRate: text = prettySampleRate(); break; case Score: text = QString::number( static_cast<int>( score() ) ); break; case Rating: text = prettyRating(); break; case PlayCount: text = QString::number( playCount() ); break; case LastPlayed: text = Amarok::verboseTimeSince( lastPlay() ); break; case Filesize: text = prettyFilesize(); break; case Mood: text = moodbar_const().state() == Moodbar::JobRunning ? i18n( "Calculating..." ) : moodbar_const().state() == Moodbar::JobQueued ? i18n( "Queued..." ) : QString::null; break; default: warning() << "Tried to get the text of a nonexistent column!" << endl; break; } return text.stripWhiteSpace();}bool MetaBundle::matchesSimpleExpression( const QString &expression, const QValueList<int> &columns ) const{ const QStringList terms = QStringList::split( ' ', expression.lower() ); bool matches = true; for( uint x = 0; matches && x < terms.count(); ++x ) { uint y = 0, n = columns.count(); for(; y < n; ++y ) if ( prettyText( columns[y] ).lower().contains( terms[x] ) ) break; matches = ( y < n ); } return matches;}void MetaBundle::reactToChanges( const QValueList<int>& columns){ // mark search dirty if we need to for (uint i = 0; !m_isSearchDirty && i < columns.count(); i++) if ((m_searchColumns & (1 << columns[i])) > 0) m_isSearchDirty = true;}bool MetaBundle::matchesFast(const QStringList &terms, ColumnMask columnMask) const{ // simple search for rating, last played, etc. makes no sense and it hurts us a // lot if we have to fetch it from the db. so zero them out columnMask &= ~( 1<<Score | 1<<Rating | 1<<PlayCount | 1<<LastPlayed | 1<<Mood ); if (m_isSearchDirty || m_searchColumns != columnMask) { // assert the size of ColumnMask is large enough. In the absence of // a compile assert mechanism, this is pretty much as good for // optimized code (ie, free) if ( sizeof(ColumnMask) < (NUM_COLUMNS / 8) ) { warning() << "ColumnMask is not big enough!\n"; } // recompute search text // There is potential for mishap here if matchesFast gets called from multiple // threads, but it's *highly* unlikely that something bad will happen m_isSearchDirty = false; m_searchColumns = columnMask; m_searchStr.setLength(0); for (int i = 0; i < NUM_COLUMNS; i++) { if ((columnMask & (1 << i)) > 0) { if (!m_searchStr.isEmpty()) m_searchStr += ' '; m_searchStr += prettyText(i).lower(); } } } // now search for (uint i = 0; i < terms.count(); i++) { if (!m_searchStr.contains(terms[i])) return false; } return true;}bool MetaBundle::matchesExpression( const QString &expression, const QValueList<int> &defaultColumns ) const{ return matchesParsedExpression( ExpressionParser::parse( expression ), defaultColumns );}bool MetaBundle::matchesParsedExpression( const ParsedExpression &data, const QValueList<int> &defaults ) const{ for( uint i = 0, n = data.count(); i < n; ++i ) //check each part for matchiness { bool b = false; //whether at least one matches for( uint ii = 0, count = data[i].count(); ii < count; ++ii ) { expression_element e = data[i][ii]; int column = -1; if( !e.field.isEmpty() ) { QString field = e.field.lower(); column = columnIndex( field ); if( column == -1 ) { column = -2; if( field == "size" ) field = "filesize"; else if( field == "filetype" ) field = "type"; else if( field == "disc" ) field = "discnumber"; else column = -1; if( column == -2 ) column = columnIndex( field ); } } if( column >= 0 ) //a field was specified and it exists { QString q = e.text, v = prettyText( column ).lower(), w = q.lower(); //q = query, v = contents of the field, w = match against it bool condition; //whether it matches, not taking e.negateation into account bool numeric; switch( column ) { case Year: case DiscNumber: case Track: case Bpm: case Bitrate: case SampleRate: case Score: case PlayCount: case LastPlayed: case Filesize: numeric = true; break; default: numeric = false; } if( column == Filesize ) { v = QString::number( filesize() ); if( w.endsWith( "m" ) ) w = QString::number( w.left( w.length()-1 ).toLong() * 1024 * 1024 ); else if( w.endsWith( "k" ) ) w = QString::number( w.left( w.length()-1 ).toLong() * 1024 ); } if( e.match == expression_element::More ) { if( numeric ) condition = v.toInt() > w.toInt(); else if( column == Rating ) condition = v.toFloat() > w.toFloat(); else if( column == Length ) { int g = v.find( ':' ), h = w.find( ':' ); condition = v.left( g ).toInt() > w.left( h ).toInt() || ( v.left( g ).toInt() == w.left( h ).toInt() && v.mid( g + 1 ).toInt() > w.mid( h + 1 ).toInt() ); } else condition = v > w; //compare the strings } else if( e.match == expression_element::Less ) { if( numeric ) condition = v.toInt() < w.toInt(); else if( column == Rating ) condition = v.toFloat() < w.toFloat(); else if( column == Length ) { int g = v.find( ':' ), h = w.find( ':' ); condition = v.left( g ).toInt() < w.left( h ).toInt() || ( v.left( g ).toInt() == w.left( h ).toInt() && v.mid( g + 1 ).toInt() < w.mid( h + 1 ).toInt() ); } else condition = v < w; } else { if( numeric ) condition = v.toInt() == w.toInt(); else if( column == Rating ) condition = v.toFloat() == w.toFloat(); else if( column == Length ) { int g = v.find( ':' ), h = w.find( ':' ); condition = v.left( g ).toInt() == w.left( h ).toInt() && v.mid( g + 1 ).toInt() == w.mid( h + 1 ).toInt(); } else condition = v.contains( q, false ); } if( condition == ( e.negate ? false : true ) ) { b = true; break; } } else //check just the default fields { for( int it = 0, end = defaults.size(); it != end; ++it ) { b = prettyText( defaults[it] ).contains( e.text, false ) == ( e.negate ? false : true ); if( ( e.negate && !b ) || ( !e.negate && b ) ) break; } if( b ) break; } } if( !b ) return false; } return true;}QStringMetaBundle::prettyTitle() const{ QString s = artist(); //NOTE this gets regressed often, please be careful! // whatever you do, handle the stream case, streams have no artist but have an excellent title //FIXME doesn't work for resume playback if( s.isEmpty() ) s = title(); else s = i18n("%1 - %2").arg( artist(), title() ); if( s.isEmpty() ) s = prettyTitle( filename() ); return s;}QStringMetaBundle::veryNiceTitle() const{ QString s; //NOTE I'm not sure, but the notes and FIXME's in the prettyTitle function should be fixed now. // If not then they do apply to this function also! if( !title().isEmpty() ) { if( !artist().isEmpty() ) s = i18n( "%1 by %2" ).arg( title(), artist() ); else s = title(); } else { s = prettyTitle( filename() ); } return s;}QStringMetaBundle::prettyTitle( const QString &filename ) //static{ QString s = filename; //just so the code is more readable //remove .part extension if it exists if (s.endsWith( ".part" )) s = s.left( s.length() - 5 ); //remove file extension, s/_/ /g and decode %2f-like sequences s = s.left( s.findRev( '.' ) ).replace( '_', ' ' ); s = KURL::decode_string( s ); return s;}QStringMetaBundle::prettyLength( int seconds, bool showHours ) //static{ if( seconds > 0 ) return prettyTime( seconds, showHours ); if( seconds == Undetermined ) return "?"; if( seconds == Irrelevant ) return "-"; return QString(); //Unavailable = ""}QStringMetaBundle::prettyTime( uint seconds, bool showHours ) //static{ QString s = QChar( ':' ); s.append( zeroPad( seconds % 60 ) ); //seconds seconds /= 60; if( showHours && seconds >= 60) { s.prepend( zeroPad( seconds % 60 ) ); //minutes s.prepend( ':' ); seconds /= 60; } //don't zeroPad the last one, as it can be greater than 2 digits s.prepend( QString::number( seconds ) ); //hours or minutes depending on above if block return s;}QStringMetaBundle::veryPrettyTime( int time ){ if( time == Undetermined ) return i18n( "?" );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?