#include "components/playlist/icon_view.hpp"
#include "components/playlist/playlist_model.hpp"
+#include "components/playlist/sorting.h"
#include "input_manager.hpp"
#include <QApplication>
#include "assert.h"
-#define RECT_SIZE 100
-#define ART_SIZE 64
-#define OFFSET (RECT_SIZE-64)/2
-#define ITEMS_SPACING 10
+#define ART_SIZE_W 110
+#define ART_SIZE_H 80
#define ART_RADIUS 5
+#define SPACER 5
-
-static const QRect drawRect = QRect( 0, 0, RECT_SIZE, RECT_SIZE );
-static const QRect artRect = drawRect.adjusted( OFFSET - 1, 2, - OFFSET, - OFFSET *2 );
-
-void PlListViewItemDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
+QString AbstractPlViewItemDelegate::getMeta( const QModelIndex & index, int meta ) const
{
- PLItem *currentItem = static_cast<PLItem*>( index.internalPointer() );
- assert( currentItem );
-
- char *meta;
+ return index.model()->index( index.row(),
+ PLModel::columnFromMeta( meta ),
+ index.parent() )
+ .data().toString();
+}
- meta = input_item_GetTitleFbName( currentItem->inputItem() );
- QString title = qfu( meta );
- free( meta );
+void AbstractPlViewItemDelegate::paintPlayingItemBg( QPainter *painter, const QStyleOptionViewItem & option ) const
+{
+ painter->save();
+ painter->setOpacity( 0.5 );
+ painter->setBrush( QBrush( Qt::gray ) );
+ painter->fillRect( option.rect, option.palette.color( QPalette::Dark ) );
+ painter->restore();
+}
- meta = input_item_GetArtist( currentItem->inputItem() );
- QString artist = qfu( meta );
- free( meta );
+QPixmap AbstractPlViewItemDelegate::getArtPixmap( const QModelIndex & index, const QSize & size ) const
+{
+ PLItem *item = static_cast<PLItem*>( index.internalPointer() );
+ assert( item );
- QString artUrl = InputManager::decodeArtURL( currentItem->inputItem() );
+ QString artUrl = InputManager::decodeArtURL( item->inputItem() );
- // look up through all children and use the first picture found
if( artUrl.isEmpty() )
{
- int children = currentItem->childCount();
- for( int i = 0; i < children; i++ )
+ for( int i = 0; i < item->childCount(); i++ )
{
- PLItem *child = currentItem->child( i );
- artUrl = InputManager::decodeArtURL( child->inputItem() );
+ artUrl = InputManager::decodeArtURL( item->child( i )->inputItem() );
if( !artUrl.isEmpty() )
break;
}
}
- /*if( option.state & QStyle::State_Selected )
- painter->fillRect(option.rect, option.palette.highlight());*/
- QApplication::style()->drawPrimitive( QStyle::PE_PanelItemViewItem, &option,
- painter );
+ QPixmap artPix;
- // picture where all the rendering happens and which will be cached
- QPixmap pix;
+ QString key = artUrl + QString("%1%2").arg(size.width()).arg(size.height());
- QString key = title + artist + artUrl
- + QString( index.data( PLModel::IsCurrentRole ).toBool() );
- if(QPixmapCache::find( key, pix ))
+ if( !QPixmapCache::find( key, artPix ))
{
- // cool, we found it in the cache
- painter->drawPixmap( option.rect, pix );
- return;
+ if( artUrl.isEmpty() || !artPix.load( artUrl ) )
+ {
+ artPix = QPixmap( ":/noart" ).scaled( size, Qt::KeepAspectRatio, Qt::SmoothTransformation );
+ }
+ else
+ {
+ artPix = artPix.scaled( size, Qt::KeepAspectRatio, Qt::SmoothTransformation );
+ QPixmapCache::insert( key, artPix );
+ }
}
- // load album art
- QPixmap artPix;
- if( artUrl.isEmpty() || !artPix.load( artUrl ) )
- artPix = QPixmap( ":/noart64" );
- else
- artPix = artPix.scaled( ART_SIZE, ART_SIZE,
- Qt::KeepAspectRatioByExpanding );
+ return artPix;
+}
- pix = QPixmap( RECT_SIZE, RECT_SIZE );
- pix.fill( Qt::transparent );
+void PlIconViewItemDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
+{
+ QString title = getMeta( index, COLUMN_TITLE );
+ QString artist = getMeta( index, COLUMN_ARTIST );
- QPainter *pixpainter = new QPainter( &pix );
+ QPixmap artPix = getArtPixmap( index, QSize( ART_SIZE_W, ART_SIZE_H ) );
- pixpainter->setRenderHints(
- QPainter::Antialiasing | QPainter::SmoothPixmapTransform |
- QPainter::TextAntialiasing );
+ QApplication::style()->drawPrimitive( QStyle::PE_PanelItemViewItem, &option,
+ painter );
+
+ painter->save();
if( index.data( PLModel::IsCurrentRole ).toBool() )
{
- pixpainter->save();
- pixpainter->setOpacity( 0.2 );
- pixpainter->setBrush( QBrush( Qt::gray ) );
- pixpainter->drawRoundedRect( 0, 0, RECT_SIZE, RECT_SIZE, ART_RADIUS, ART_RADIUS );
- pixpainter->restore();
+ painter->save();
+ painter->setOpacity( 0.2 );
+ painter->setBrush( QBrush( Qt::gray ) );
+ painter->drawRoundedRect( option.rect.adjusted( 0, 0, -1, -1 ), ART_RADIUS, ART_RADIUS );
+ painter->restore();
}
- // Draw the drop shadow
- pixpainter->save();
- pixpainter->setOpacity( 0.7 );
- pixpainter->setBrush( QBrush( Qt::gray ) );
- pixpainter->drawRoundedRect( artRect.adjusted( 2, 2, 2, 2 ), ART_RADIUS, ART_RADIUS );
- pixpainter->restore();
+ QRect artRect( option.rect.x() + 5 + ( ART_SIZE_W - artPix.width() ) / 2,
+ option.rect.y() + 5 + ( ART_SIZE_H - artPix.height() ) / 2,
+ artPix.width(), artPix.height() );
- // Draw the art pix
+ // Draw the drop shadow
+ painter->save();
+ painter->setOpacity( 0.7 );
+ painter->setBrush( QBrush( Qt::darkGray ) );
+ painter->setPen( Qt::NoPen );
+ painter->drawRoundedRect( artRect.adjusted( 0, 0, 2, 2 ), ART_RADIUS, ART_RADIUS );
+ painter->restore();
+
+ // Draw the art pixmap
QPainterPath artRectPath;
artRectPath.addRoundedRect( artRect, ART_RADIUS, ART_RADIUS );
- pixpainter->setClipPath( artRectPath );
- pixpainter->drawPixmap( artRect, artPix );
- pixpainter->setClipping( false );
+ painter->setClipPath( artRectPath );
+ painter->drawPixmap( artRect, artPix );
+ painter->setClipping( false );
- QColor text = qApp->palette().text().color();
+ if( option.state & QStyle::State_Selected )
+ painter->setPen( option.palette.color( QPalette::HighlightedText ) );
- // Draw title
- pixpainter->setPen( text );
- QFont font;
+ QFont font( index.data( Qt::FontRole ).value<QFont>() );
font.setPointSize( 7 );
- font.setItalic(true);
- font.setBold( index.data( Qt::FontRole ).value<QFont>().bold() );
- pixpainter->setFont( font );
- QFontMetrics fm = pixpainter->fontMetrics();
- QRect textRect = drawRect.adjusted( 1, ART_SIZE + 4, 0, -1 );
- textRect.setHeight( fm.height() + 2 );
-
- pixpainter->drawText( textRect,
+
+ // Draw title
+ font.setItalic( true );
+ painter->setFont( font );
+
+ QFontMetrics fm = painter->fontMetrics();
+ QRect textRect = option.rect.adjusted( 1, ART_SIZE_H + 10, 0, -1 );
+ textRect.setHeight( fm.height() );
+
+ painter->drawText( textRect,
fm.elidedText( title, Qt::ElideRight, textRect.width() ),
QTextOption( Qt::AlignCenter ) );
// Draw artist
- pixpainter->setPen( text.lighter( 240 ) );
+ painter->setPen( painter->pen().color().lighter( 150 ) );
font.setItalic( false );
- pixpainter->setFont( font );
- fm = pixpainter->fontMetrics();
+ painter->setFont( font );
+ fm = painter->fontMetrics();
+
+ textRect.moveTop( textRect.bottom() + 1 );
+
+ painter->drawText( textRect,
+ fm.elidedText( artist, Qt::ElideRight, textRect.width() ),
+ QTextOption( Qt::AlignCenter ) );
+
+ painter->restore();
+}
+
+QSize PlIconViewItemDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
+{
+ QFont f;
+ f.setPointSize( 7 );
+ f.setBold( true );
+ QFontMetrics fm( f );
+ int textHeight = fm.height();
+ QSize sz ( ART_SIZE_W + 2 * SPACER,
+ ART_SIZE_H + 3 * SPACER + 2 * textHeight + 1 );
+ return sz;
+}
+
+
+#define LISTVIEW_ART_SIZE 45
+
+void PlListViewItemDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
+{
+ QModelIndex parent = index.parent();
+ QModelIndex i;
+
+ QString title = getMeta( index, COLUMN_TITLE );
+ QString duration = getMeta( index, COLUMN_DURATION );
+ if( !duration.isEmpty() ) title += QString(" [%1]").arg( duration );
+
+ QString artist = getMeta( index, COLUMN_ARTIST );
+ QString album = getMeta( index, COLUMN_ALBUM );
+ QString trackNum = getMeta( index, COLUMN_TRACK_NUMBER );
+ QString artistAlbum = artist
+ + ( artist.isEmpty() ? QString() : QString( ": " ) )
+ + album
+ + ( album.isEmpty() || trackNum.isEmpty() ?
+ QString() : QString( " [#%1]" ).arg( trackNum ) );
+
+ QPixmap artPix = getArtPixmap( index, QSize( LISTVIEW_ART_SIZE, LISTVIEW_ART_SIZE ) );
+
+ //Draw selection rectangle
+ QApplication::style()->drawPrimitive( QStyle::PE_PanelItemViewItem, &option, painter );
+
+ //Paint background if item is playing
+ if( index.data( PLModel::IsCurrentRole ).toBool() )
+ paintPlayingItemBg( painter, option );
+
+ QRect artRect( artPix.rect() );
+ artRect.moveCenter( QPoint( artRect.center().x() + 3,
+ option.rect.center().y() ) );
+ //Draw album art
+ painter->drawPixmap( artRect, artPix );
+
+ //Start drawing text
+ painter->save();
+
+ if( option.state & QStyle::State_Selected )
+ painter->setPen( option.palette.color( QPalette::HighlightedText ) );
+
+ QTextOption textOpt( Qt::AlignVCenter | Qt::AlignLeft );
+ textOpt.setWrapMode( QTextOption::NoWrap );
+
+ QFont f( index.data( Qt::FontRole ).value<QFont>() );
+ //Draw title info
+ f.setItalic( true );
+ painter->setFont( f );
+ QFontMetrics fm( painter->fontMetrics() );
- textRect = textRect.adjusted( 0, textRect.height(),
- 0, textRect.height() );
- pixpainter->drawText( textRect,
- fm.elidedText( artist, Qt::ElideRight, textRect.width() ),
- QTextOption( Qt::AlignCenter ) );
+ QRect textRect = option.rect.adjusted( LISTVIEW_ART_SIZE + 10, 0, -10, 0 );
+ if( !artistAlbum.isEmpty() )
+ {
+ textRect.setHeight( fm.height() );
+ textRect.moveBottom( option.rect.center().y() - 1 );
+ }
- delete pixpainter; // Ensure all paint operations have finished
+ painter->drawText( textRect,
+ fm.elidedText( title, Qt::ElideRight, textRect.width() ),
+ textOpt );
- // Here real drawing happens
- painter->drawPixmap( option.rect, pix );
+ // Draw artist and album info
+ if( !artistAlbum.isEmpty() )
+ {
+ f.setItalic( false );
+ painter->setFont( f );
+ fm = painter->fontMetrics();
- // Cache the rendering
- QPixmapCache::insert( key, pix );
+ textRect.moveTop( textRect.bottom() + 2 );
+
+ painter->drawText( textRect,
+ fm.elidedText( artistAlbum, Qt::ElideRight, textRect.width() ),
+ textOpt );
+ }
+
+ painter->restore();
}
QSize PlListViewItemDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
- return QSize( RECT_SIZE, RECT_SIZE);
+ QFont f;
+ f.setBold( true );
+ QFontMetrics fm( f );
+ int height = qMax( LISTVIEW_ART_SIZE, 2 * fm.height() + 2 ) + 6;
+ return QSize( 0, height );
}
-
PlIconView::PlIconView( PLModel *model, QWidget *parent ) : QListView( parent )
{
+ PlIconViewItemDelegate *delegate = new PlIconViewItemDelegate( this );
+
setModel( model );
setViewMode( QListView::IconMode );
setMovement( QListView::Static );
setResizeMode( QListView::Adjust );
- setGridSize( QSize( RECT_SIZE, RECT_SIZE ) );
- setUniformItemSizes( true );
- setSpacing( ITEMS_SPACING );
+ setGridSize( delegate->sizeHint() );
setWrapping( true );
+ setUniformItemSizes( true );
+ setSelectionMode( QAbstractItemView::ExtendedSelection );
+ setDragEnabled(true);
+ /* dropping in QListView::IconMode does not seem to work */
+ //setAcceptDrops( true );
+ //setDropIndicatorShown(true);
+
+ setItemDelegate( delegate );
+}
+
+PlListView::PlListView( PLModel *model, QWidget *parent ) : QListView( parent )
+{
+ setModel( model );
+ setViewMode( QListView::ListMode );
+ setUniformItemSizes( true );
setSelectionMode( QAbstractItemView::ExtendedSelection );
+ setAlternatingRowColors( true );
+ setDragEnabled(true);
setAcceptDrops( true );
+ setDropIndicatorShown(true);
- PlListViewItemDelegate *pl = new PlListViewItemDelegate( this );
- setItemDelegate( pl );
+ PlListViewItemDelegate *delegate = new PlListViewItemDelegate( this );
+ setItemDelegate( delegate );
}