void PlaylistItem::drawRating( QPainter *p ) { int gray = 0; if( this == listView()->m_hoveredRating || ( isSelected() && listView()->m_selCount > 1 && listView()->m_hoveredRating && listView()->m_hoveredRating->isSelected() ) ) { const int pos = listView()->viewportToContents( listView()->viewport()->mapFromGlobal( QCursor::pos() ) ).x(); gray = ratingAtPoint( pos ); } drawRating( p, ( rating() + 1 ) / 2, gray / 2, rating() % 2 ); }
void RatingComboBoxDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { QVariant value = index.data(Qt::DisplayRole); bool selectable = index.flags() & Qt::ItemIsSelectable; if (value.type() == QVariant::Int) { painter->save(); drawBackground(painter, option, index); drawDisplay(painter, option, option.rect, QString()); // our custom painting drawRating(painter, option.rect, value.toInt(), selectable); drawFocus(painter, option, option.rect); painter->restore(); } else { return QItemDelegate::paint(painter, option, index); } }
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 <*****@*****.**> Copyright (C) 2000,2003 Charles Samuels <*****@*****.**> 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 ); static const QPixmap pixstop = Amarok::getPNG( "currenttrack_stop_small" ), pixrepeat = Amarok::getPNG( "currenttrack_repeat_small" ); //figure out if we are in the actual physical first column if( column == listView()->m_firstColumn && num ) { //margin, height const uint m = 2, h = height() - m; const QString str = QString::number( queue ); const uint qw = painter->fontMetrics().width( str ), sw = pixstop.width(), rw = pixrepeat.width(), qh = painter->fontMetrics().height(), sh = pixstop.height(), rh = pixrepeat.height(); //maxwidth const uint mw = kMax( qw, kMax( rw, sw ) ); //width of first & second column of pixmaps const uint w1 = ( num == 3 ) ? kMax( qw, rw ) : ( num == 2 && isCurrent ) ? kMax( repeat ? rw : 0, kMax( stop ? sw : 0, queue ? qw : 0 ) ) : ( num == 2 ) ? qw : queue ? qw : repeat ? rw : stop ? sw : 0, w2 = ( num == 3 ) ? sw : ( num == 2 && !isCurrent ) ? sw : 0; //phew //ellipse width, total width const uint ew = 16, tw = w1 + w2 + m * ( w2 ? 2 : 1 ); p.setBrush( cg.highlight() ); p.setPen( cg.highlight().dark() ); //TODO blend with background color p.drawEllipse( width - tw - ew/2, m / 2, ew, h ); p.drawRect( width - tw, m / 2, tw, h ); p.setPen( cg.highlight() ); p.drawLine( width - tw, m/2 + 1, width - tw, h - m/2 ); int x = width - m - mw, y = height() / 2, tmp = 0; const bool multi = ( isCurrent && num >= 2 ); if( queue ) { //draw the shadowed inner text //NOTE we can't set an arbituary font size or family, these settings are already optional //and user defaults should also take presidence if no playlist font has been selected //const QFont smallFont( "Arial", (playNext > 9) ? 9 : 12 ); //p->setFont( smallFont ); //TODO the shadow is hard to do well when using a dark font color //TODO it also looks cluttered for small font sizes //p->setPen( cg.highlightedText().dark() ); //p->drawText( width - w + 2, 3, w, h-1, Qt::AlignCenter, str ); if( !multi ) tmp = -(qh / 2); y += tmp; p.setPen( cg.highlightedText() ); p.drawText( x, y, -x + width, multi ? h/2 : qh, Qt::AlignCenter, str ); y -= tmp; if( isCurrent ) y -= height() / 2; else x -= m + w2; } if( repeat ) { if( multi ) tmp = (h/2 - rh)/2 + ( num == 2 && stop ? 0 : 1 ); else tmp = -(rh / 2); y += tmp; p.drawPixmap( x, y, pixrepeat ); y -= tmp; if( num == 3 ) { x -= m + w2 + 2; y = height() / 2; } else y -= height() / 2; } if( stop ) { if( multi && num != 3 ) tmp = m + (h/2 - sh)/2; else tmp = -(sh / 2); y += tmp; p.drawPixmap( x, y, pixstop ); y -= tmp; } } if( this != listView()->currentTrack() && !isSelected() ) { p.setPen( QPen( cg.mid(), 0, Qt::SolidLine ) ); p.drawLine( width - 1, 0, width - 1, height() - 1 ); } p.end(); painter->drawPixmap( 0, 0, buf ); }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Draw info on selected item: /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void drawMLinfo(){ static u64 lastMenuChange = 0; static int lastSelected = -1; OSL_FONT *font = fontNormal; OSL_IMAGE *tmpCoverArt = NULL; if (mediaLibraryStatus != STATUS_QUERYMENU) return; skinGetPosition("POS_MEDIALIBRARY_INFO_BKG", tempPos); oslDrawImageXY(infoBkg, tempPos[0], tempPos[1]); oslSetFont(font); skinGetColor("RGBA_LABEL_TEXT", tempColor); skinGetColor("RGBA_LABEL_TEXT_SHADOW", tempColorShadow); setFontStyle(fontNormal, defaultTextSize, RGBA(tempColor[0], tempColor[1], tempColor[2], tempColor[3]), RGBA(tempColorShadow[0], tempColorShadow[1], tempColorShadow[2], tempColorShadow[3]), INTRAFONT_ALIGN_LEFT); switch (mlQueryType) { case QUERY_COUNT: case QUERY_COUNT_RATING: case QUERY_COUNT_ARTIST: skinGetPosition("POS_MEDIALIBRARY_TOTAL_TRACKS_LABEL", tempPos); oslDrawString(tempPos[0], tempPos[1], langGetString("TOTAL_TRACKS")); skinGetPosition("POS_MEDIALIBRARY_TOTAL_TIME_LABEL", tempPos); oslDrawString(tempPos[0], tempPos[1], langGetString("TOTAL_TIME")); skinGetColor("RGBA_TEXT", tempColor); skinGetColor("RGBA_TEXT_SHADOW", tempColorShadow); setFontStyle(fontNormal, defaultTextSize, RGBA(tempColor[0], tempColor[1], tempColor[2], tempColor[3]), RGBA(tempColorShadow[0], tempColorShadow[1], tempColorShadow[2], tempColorShadow[3]), INTRAFONT_ALIGN_LEFT); snprintf(buffer, sizeof(buffer), "%.f", MLresult[commonMenu.selected - mlBufferPosition]->intField01); skinGetPosition("POS_MEDIALIBRARY_TOTAL_TRACKS_VALUE", tempPos); oslDrawString(tempPos[0], tempPos[1], buffer); formatHHMMSS(MLresult[commonMenu.selected - mlBufferPosition]->intField02, buffer, sizeof(buffer)); skinGetPosition("POS_MEDIALIBRARY_TOTAL_TIME_VALUE", tempPos); oslDrawString(tempPos[0], tempPos[1], buffer); break; case QUERY_SINGLE_ENTRY: skinGetPosition("POS_MEDIALIBRARY_GENRE_LABEL", tempPos); oslDrawString(tempPos[0], tempPos[1], langGetString("GENRE")); skinGetPosition("POS_MEDIALIBRARY_YEAR_LABEL", tempPos); oslDrawString(tempPos[0], tempPos[1], langGetString("YEAR")); skinGetPosition("POS_MEDIALIBRARY_TIME_LABEL", tempPos); oslDrawString(tempPos[0], tempPos[1], langGetString("TIME")); skinGetPosition("POS_MEDIALIBRARY_RATING_LABEL", tempPos); oslDrawString(tempPos[0], tempPos[1], langGetString("RATING")); skinGetPosition("POS_MEDIALIBRARY_PLAYED_LABEL", tempPos); oslDrawString(tempPos[0], tempPos[1], langGetString("PLAYED")); skinGetColor("RGBA_TEXT", tempColor); skinGetColor("RGBA_TEXT_SHADOW", tempColorShadow); setFontStyle(fontNormal, defaultTextSize, RGBA(tempColor[0], tempColor[1], tempColor[2], tempColor[3]), RGBA(tempColorShadow[0], tempColorShadow[1], tempColorShadow[2], tempColorShadow[3]), INTRAFONT_ALIGN_LEFT); skinGetPosition("POS_MEDIALIBRARY_GENRE_VALUE", tempPos); oslDrawString(tempPos[0], tempPos[1], MLresult[commonMenu.selected - mlBufferPosition]->genre); skinGetPosition("POS_MEDIALIBRARY_YEAR_VALUE", tempPos); oslDrawString(tempPos[0], tempPos[1], MLresult[commonMenu.selected - mlBufferPosition]->year); formatHHMMSS(MLresult[commonMenu.selected - mlBufferPosition]->seconds, buffer, sizeof(buffer)); skinGetPosition("POS_MEDIALIBRARY_TIME_VALUE", tempPos); oslDrawString(tempPos[0], tempPos[1], buffer); skinGetPosition("POS_MEDIALIBRARY_RATING_VALUE", tempPos); drawRating(tempPos[0], tempPos[1], MLresult[commonMenu.selected - mlBufferPosition]->rating); skinGetPosition("POS_MEDIALIBRARY_PLAYED_VALUE", tempPos); snprintf(buffer, sizeof(buffer), "%i", MLresult[commonMenu.selected - mlBufferPosition]->played); oslDrawString(tempPos[0], tempPos[1], buffer); if (commonMenu.selected != lastSelected){ sceRtcGetCurrentTick (&lastMenuChange); lastSelected = commonMenu.selected; if (coverArt){ oslDeleteImage(coverArt); coverArt = NULL; } coverArtFailed = 0; }else if (!coverArt && !coverArtFailed){ u64 currentTime; sceRtcGetCurrentTick(¤tTime); if (currentTime - lastMenuChange > COVERTART_DELAY){ char dirName[264]; int size = 0; cpuBoost(); snprintf(dirName, sizeof(dirName), "%s", MLresult[commonMenu.selected - mlBufferPosition]->shortpath); directoryUp(dirName); //Look for folder.jpg in the same directory: snprintf(buffer, sizeof(buffer), "%s/%s", dirName, "folder.jpg"); size = fileExists(buffer); if (size > 0 && size <= MAX_IMAGE_DIMENSION) { tmpCoverArt = oslLoadImageFileJPG(buffer, OSL_IN_RAM | OSL_SWIZZLED, OSL_PF_8888); } else { //Look for cover.jpg in same directory: snprintf(buffer, sizeof(buffer), "%s/%s", dirName, "cover.jpg"); size = fileExists(buffer); if (size > 0 && size <= MAX_IMAGE_DIMENSION) tmpCoverArt = oslLoadImageFileJPG(buffer, OSL_IN_RAM | OSL_SWIZZLED, OSL_PF_8888); } if (tmpCoverArt){ int coverArtWidth = skinGetParam("MEDIALIBRARY_COVERART_WIDTH"); int coverArtHeight = skinGetParam("MEDIALIBRARY_COVERART_HEIGHT"); coverArt = oslScaleImageCreate(tmpCoverArt, OSL_IN_RAM | OSL_SWIZZLED, coverArtWidth, coverArtHeight, OSL_PF_8888); oslDeleteImage(tmpCoverArt); tmpCoverArt = NULL; coverArt->stretchX = coverArtWidth; coverArt->stretchY = coverArtHeight; }else{ coverArtFailed = 1; } cpuRestore(); } } if (coverArt){ skinGetPosition("POS_MEDIALIBRARY_COVERART", tempPos); oslDrawImageXY(coverArt, tempPos[0], tempPos[1]); } break; } }