playlistitem.cpp
来自「Amarok是一款在LINUX或其他类UNIX操作系统中运行的音频播放器软件。 」· C++ 代码 · 共 1,153 行 · 第 1/3 页
CPP
1,153 行
{ const QRect r = listView()->itemRect( this ); if( !r.isValid() ) return; listView()->viewport()->update( listView()->header()->sectionPos( column ) - listView()->contentsX() + 1, r.y() + 1, listView()->header()->sectionSize( column ) - 2, height() - 2 );}boolPlaylistItem::operator== ( const PlaylistItem & item ) const{ return item.url() == this->url();}boolPlaylistItem::operator< ( const PlaylistItem & item ) const{ return item.url() < this->url();}PlaylistItem*PlaylistItem::nextInAlbum() const{ if( !m_album ) return 0; const int index = m_album->tracks.findRef( this ); if( index == int(m_album->tracks.count() - 1) ) return 0; if( index != -1 ) return m_album->tracks.at( index + 1 ); if( track() ) for( int i = 0, n = m_album->tracks.count(); i < n; ++i ) if( m_album->tracks.at( i )->discNumber() > discNumber() || ( m_album->tracks.at( i )->discNumber() == discNumber() && m_album->tracks.at( i )->track() > track() ) ) return m_album->tracks.at( i ); else for( QListViewItemIterator it( const_cast<PlaylistItem*>(this), QListViewItemIterator::Visible ); *it; ++it ) #define pit static_cast<PlaylistItem*>( *it ) if( pit != this && pit->m_album == m_album && !pit->track() ) return pit; #undef pit return 0;}PlaylistItem*PlaylistItem::prevInAlbum() const{ if( !m_album ) return 0; const int index = m_album->tracks.findRef( this ); if( index == 0 ) return 0; if( index != -1 ) return m_album->tracks.at( index - 1 ); if( track() ) for( int i = m_album->tracks.count() - 1; i >= 0; --i ) if( m_album->tracks.at( i )->track() && ( m_album->tracks.at( i )->discNumber() < discNumber() || ( m_album->tracks.at( i )->discNumber() == discNumber() && m_album->tracks.at( i )->track() < track() ) ) ) return m_album->tracks.at( i ); else for( QListViewItemIterator it( const_cast<PlaylistItem*>(this), QListViewItemIterator::Visible ); *it; --it ) #define pit static_cast<PlaylistItem*>( *it ) if( pit != this && pit->m_album == m_album && !pit->track() ) return pit; #undef pit return 0;}/////////////////////////////////////////////////////////////////////////////////////// PRIVATE METHODS/////////////////////////////////////////////////////////////////////////////////////intPlaylistItem::compare( QListViewItem *i, int col, bool ascending ) const{ #define i static_cast<PlaylistItem*>(i) if( Playlist::instance()->dynamicMode() && (isEnabled() != i->isEnabled()) ) return isEnabled() ? 1 : -1; //damn C++ and its lack of operator<=> #define cmp(a,b) ( (a < b ) ? -1 : ( a > b ) ? 1 : 0 ) switch( col ) { case Track: return cmp( track(), i->track() ); case Score: return cmp( score(), i->score() ); case Rating: return cmp( rating(), i->rating() ); case Length: return cmp( length(), i->length() ); case PlayCount: return cmp( playCount(), i->playCount() ); case LastPlayed: return cmp( lastPlay(), i->lastPlay() ); case Bitrate: return cmp( bitrate(), i->bitrate() ); case Bpm: return cmp( bpm(), i->bpm() ); case Filesize: return cmp( filesize(), i->filesize() ); case Mood: return cmp( moodbar_const().hueSort(), i->moodbar_const().hueSort() ); case Year: if( year() == i->year() ) return compare( i, Artist, ascending ); return cmp( year(), i->year() ); case DiscNumber: if( discNumber() == i->discNumber() ) return compare( i, Track, true ) * (ascending ? 1 : -1); return cmp( discNumber(), i->discNumber() ); } #undef cmp #undef i QString a = text( col ).lower(); QString b = i->text( col ).lower(); switch( col ) { case Type: a = a.rightJustify( b.length(), '0' ); b = b.rightJustify( a.length(), '0' ); break; case Artist: if( a == b ) //if same artist, try to sort by album return compare( i, Album, ascending ); else { if( a.startsWith( "the ", false ) ) a = a.mid( 4 ); if( b.startsWith( "the ", false ) ) b = b.mid( 4 ); } break; case Album: if( a == b ) //if same album, try to sort by track //TODO only sort in ascending order? return compare( i, DiscNumber, true ) * (ascending ? 1 : -1); break; } return QString::localeAwareCompare( a, b );}void PlaylistItem::paintCell( QPainter *painter, const QColorGroup &cg, int column, int width, int align ){ //TODO add spacing on either side of items //p->translate( 2, 0 ); width -= 3; // Don't try to draw if width or height is 0, as this crashes Qt if( !painter || !listView() || width <= 0 || height() == 0 ) return; static const QImage currentTrackLeft = locate( "data", "amarok/images/currenttrack_bar_left.png" ); static const QImage currentTrackMid = locate( "data", "amarok/images/currenttrack_bar_mid.png" ); static const QImage currentTrackRight = locate( "data", "amarok/images/currenttrack_bar_right.png" ); if( column == Mood && !moodbar().dataExists() ) moodbar().load(); // Only has an effect the first time // The moodbar column can have text in it, like "Calculating". // moodbarType is 0 if column != Mood, 1 if we're displaying // a moodbar, and 2 if we're displaying text const int moodbarType = column != Mood ? 0 : moodbar().state() == Moodbar::Loaded ? 1 : 2; const QString colText = text( column ); const bool isCurrent = this == listView()->currentTrack(); QPixmap buf( width, height() ); QPainter p( &buf, true ); if( isCurrent ) { static paintCacheItem paintCache[NUM_COLUMNS]; // Convert intensity to string, so we can use it as a key const QString colorKey = QString::number( glowIntensity ); const bool cacheValid = paintCache[column].width == width && paintCache[column].height == height() && paintCache[column].text == colText && paintCache[column].font == painter->font() && paintCache[column].color == glowBase && paintCache[column].selected == isSelected() && !s_pixmapChanged; // If any parameter changed, we must regenerate all pixmaps if ( !cacheValid ) { for( int i = 0; i < NUM_COLUMNS; ++i) paintCache[i].map.clear(); s_pixmapChanged = false; } // Determine if we need to repaint the pixmap, or paint from cache if ( paintCache[column].map.find( colorKey ) == paintCache[column].map.end() ) { // Update painting cache paintCache[column].width = width; paintCache[column].height = height(); paintCache[column].text = colText; paintCache[column].font = painter->font(); paintCache[column].color = glowBase; paintCache[column].selected = isSelected(); QColor bg; if( isSelected() ) bg = listView()->colorGroup().highlight(); else bg = isAlternate() ? listView()->alternateBackground() : listView()->viewport()->backgroundColor(); buf.fill( bg ); // Draw column divider line p.setPen( listView()->viewport()->colorGroup().mid() ); p.drawLine( width - 1, 0, width - 1, height() - 1 ); // Here we draw the background bar graphics for the current track: // // Illustration of design, L = Left, M = Middle, R = Right: // <LMMMMMMMMMMMMMMMR> int leftOffset = 0; int rightOffset = 0; int margin = listView()->itemMargin(); const float colorize = 0.8; const double intensity = 1.0 - glowIntensity * 0.021; // Left part if( column == listView()->m_firstColumn ) { QImage tmpImage = currentTrackLeft.smoothScale( 1, height(), QImage::ScaleMax ); KIconEffect::colorize( tmpImage, glowBase, colorize ); imageTransparency( tmpImage, intensity ); p.drawImage( 0, 0, tmpImage, 0, 0, tmpImage.width() - 1 ); //HACK leftOffset = tmpImage.width() - 1; //HACK Subtracting 1, to work around the black line bug margin += 6; } // Right part else if( column == Playlist::instance()->mapToLogicalColumn( Playlist::instance()->numVisibleColumns() - 1 ) ) { QImage tmpImage = currentTrackRight.smoothScale( 1, height(), QImage::ScaleMax ); KIconEffect::colorize( tmpImage, glowBase, colorize ); imageTransparency( tmpImage, intensity ); p.drawImage( width - tmpImage.width(), 0, tmpImage ); rightOffset = tmpImage.width(); margin += 6; } // Middle part // Here we scale the one pixel wide middel image to stretch to the full column width. QImage tmpImage = currentTrackMid.copy(); KIconEffect::colorize( tmpImage, glowBase, colorize ); imageTransparency( tmpImage, intensity ); tmpImage = tmpImage.smoothScale( width - leftOffset - rightOffset, height() ); p.drawImage( leftOffset, 0, tmpImage ); // Draw the pixmap, if present int leftMargin = margin; if ( pixmap( column ) ) { p.drawPixmap( leftMargin, height() / 2 - pixmap( column )->height() / 2, *pixmap( column ) ); leftMargin += pixmap( column )->width() + 2; } if( align != Qt::AlignCenter ) align |= Qt::AlignVCenter; if( column != Rating && moodbarType != 1 ) { // Draw the text static QFont font; static int minbearing = 1337 + 666; if( minbearing == 2003 || font != painter->font() ) { font = painter->font(); minbearing = painter->fontMetrics().minLeftBearing() + painter->fontMetrics().minRightBearing(); } const bool italic = font.italic(); int state = EngineController::engine()->state(); if( state == Engine::Playing || state == Engine::Paused ) font.setItalic( !italic ); p.setFont( font ); p.setPen( cg.highlightedText() );// paint.setPen( glowText ); const int _width = width - leftMargin - margin + minbearing - 1; // -1 seems to be necessary const QString _text = KStringHandler::rPixelSqueeze( colText, painter->fontMetrics(), _width ); p.drawText( leftMargin, 0, _width, height(), align, _text ); font.setItalic( italic ); p.setFont( font ); } paintCache[column].map[colorKey] = buf; } else p.drawPixmap( 0, 0, paintCache[column].map[colorKey] ); if( column == Rating ) drawRating( &p ); if( moodbarType == 1 ) drawMood( &p, width, height() ); } else { const QColorGroup _cg = ( !exists() || !isEnabled() ) ? listView()->palette().disabled() : listView()->palette().active(); QColor bg = isSelected() ? _cg.highlight() : isAlternate() ? listView()->alternateBackground() : listView()->viewport()->backgroundColor(); #if KDE_IS_VERSION( 3, 3, 91 ) if( listView()->shadeSortColumn() && !isSelected() && listView()->columnSorted() == column ) { /* from klistview.cpp Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org> Copyright (C) 2000,2003 Charles Samuels <charles@kde.org> Copyright (C) 2000 Peter Putzer */ if ( bg == Qt::black ) bg = QColor(55, 55, 55); // dark gray else { int h,s,v; bg.hsv(&h, &s, &v); if ( v > 175 ) bg = bg.dark(104); else bg = bg.light(120); } } #endif const QColor textc = isSelected() ? _cg.highlightedText() : _cg.text(); buf.fill( bg ); // Draw column divider line if( !isSelected() ) { p.setPen( listView()->viewport()->colorGroup().mid() ); p.drawLine( width - 1, 0, width - 1, height() - 1 ); } // Draw the pixmap, if present int margin = listView()->itemMargin(), leftMargin = margin; if ( pixmap( column ) ) { p.drawPixmap( leftMargin, height() / 2 - pixmap( column )->height() / 2, *pixmap( column ) ); leftMargin += pixmap( column )->width(); } if( align != Qt::AlignCenter ) align |= Qt::AlignVCenter; if( column == Rating ) drawRating( &p ); else if( moodbarType == 1 ) drawMood( &p, width, height() ); else { // Draw the text static QFont font; static int minbearing = 1337 + 666; //can be 0 or negative, 2003 is less likely if( minbearing == 2003 || font != painter->font() ) { font = painter->font(); //getting your bearings can be expensive, so we cache them minbearing = painter->fontMetrics().minLeftBearing() + painter->fontMetrics().minRightBearing(); } p.setFont( font ); p.setPen( ( m_isNew && isEnabled() && !isSelected() ) ? AmarokConfig::newPlaylistItemsColor() : textc ); const int _width = width - leftMargin - margin + minbearing - 1; // -1 seems to be necessary const QString _text = KStringHandler::rPixelSqueeze( colText, painter->fontMetrics(), _width ); p.drawText( leftMargin, 0, _width, height(), align, _text ); } } /// Track action symbols const int queue = listView()->m_nextTracks.findRef( this ) + 1; const bool stop = ( this == listView()->m_stopAfterTrack ); const bool repeat = Amarok::repeatTrack() && isCurrent; const uint num = ( queue ? 1 : 0 ) + ( stop ? 1 : 0 ) + ( repeat ? 1 : 0 );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?