#include "components/playlist/icon_view.hpp"
#include "components/playlist/playlist_model.hpp"
+#include "components/playlist/sorting.h"
#include "input_manager.hpp"
+#include <QApplication>
#include <QPainter>
#include <QRect>
#include <QStyleOptionViewItem>
-#include <QApplication>
+#include <QFontMetrics>
+#include <QPixmapCache>
#include "assert.h"
-#define RECT_SIZE 100
-#define ART_SIZE 64
-#define OFFSET (100-64)/2
-#define ITEMS_SPACING 10
+#define ART_SIZE_W 110
+#define ART_SIZE_H 80
#define ART_RADIUS 5
+#define SPACER 5
-void PlListViewItemDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
+QString AbstractPlViewItemDelegate::getMeta( const QModelIndex & index, int meta ) const
{
- painter->setRenderHints( QPainter::Antialiasing | QPainter::SmoothPixmapTransform );
+ return index.model()->index( index.row(),
+ PLModel::columnFromMeta( meta ),
+ index.parent() )
+ .data().toString();
+}
- /*if( option.state & QStyle::State_Selected )
- painter->fillRect(option.rect, option.palette.highlight());*/
- QApplication::style()->drawPrimitive( QStyle::PE_PanelItemViewItem, &option, painter );
+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();
+}
- PLItem *currentItem = static_cast<PLItem*>( index.internalPointer() );
- assert( currentItem );
+QPixmap AbstractPlViewItemDelegate::getArtPixmap( const QModelIndex & index, const QSize & size ) const
+{
+ PLItem *item = static_cast<PLItem*>( index.internalPointer() );
+ assert( item );
- QPixmap pix;
- QString url = InputManager::decodeArtURL( currentItem->inputItem() );
+ QString artUrl = InputManager::decodeArtURL( item->inputItem() );
- if( !url.isEmpty() && pix.load( url ) )
+ if( artUrl.isEmpty() )
{
- pix = pix.scaled( ART_SIZE, ART_SIZE, Qt::KeepAspectRatioByExpanding );
+ for( int i = 0; i < item->childCount(); i++ )
+ {
+ artUrl = InputManager::decodeArtURL( item->child( i )->inputItem() );
+ if( !artUrl.isEmpty() )
+ break;
+ }
}
- else
+
+ QPixmap artPix;
+
+ QString key = artUrl + QString("%1%2").arg(size.width()).arg(size.height());
+
+ if( !QPixmapCache::find( key, artPix ))
{
- pix = QPixmap( ":/noart64" );
+ 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 );
+ }
}
- QRect artRect = option.rect.adjusted( OFFSET - 1, 0, - OFFSET, - OFFSET *2 );
- QPainterPath artRectPath;
- artRectPath.addRoundedRect( artRect, ART_RADIUS, ART_RADIUS );
+ return artPix;
+}
+
+void PlIconViewItemDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
+{
+ QString title = getMeta( index, COLUMN_TITLE );
+ QString artist = getMeta( index, COLUMN_ARTIST );
+
+ QPixmap artPix = getArtPixmap( index, QSize( ART_SIZE_W, ART_SIZE_H ) );
+
+ QApplication::style()->drawPrimitive( QStyle::PE_PanelItemViewItem, &option,
+ painter );
+
+ painter->save();
+
+ if( index.data( PLModel::IsCurrentRole ).toBool() )
+ {
+ 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();
+ }
+
+ 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 drop shadow
painter->save();
painter->setOpacity( 0.7 );
- painter->setBrush( QBrush( Qt::gray ) );
- painter->drawRoundedRect( artRect.adjusted( 2, 2, 2, 2 ), ART_RADIUS, ART_RADIUS );
+ 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 );
painter->setClipPath( artRectPath );
- painter->drawPixmap( artRect, pix );
+ painter->drawPixmap( artRect, artPix );
painter->setClipping( false );
- painter->setFont( QFont( "Verdana", 7 ) );
+ if( option.state & QStyle::State_Selected )
+ painter->setPen( option.palette.color( QPalette::HighlightedText ) );
- QRect textRect = option.rect.adjusted( 1, ART_SIZE + 2, -1, -1 );
- painter->drawText( textRect, qfu( input_item_GetTitleFbName( currentItem->inputItem() ) ),
- QTextOption( Qt::AlignCenter ) );
+ QFont font( index.data( Qt::FontRole ).value<QFont>() );
+ font.setPointSize( 7 );
+ // 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
+ painter->setPen( painter->pen().color().lighter( 150 ) );
+ font.setItalic( false );
+ 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 PlListViewItemDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
+QSize PlIconViewItemDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
- return QSize( RECT_SIZE, RECT_SIZE);
+ 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() );
+
+ 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 );
+ }
+
+ painter->drawText( textRect,
+ fm.elidedText( title, Qt::ElideRight, textRect.width() ),
+ textOpt );
+
+ // Draw artist and album info
+ if( !artistAlbum.isEmpty() )
+ {
+ f.setItalic( false );
+ painter->setFont( f );
+ fm = painter->fontMetrics();
+
+ 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
+{
+ 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( 100, 100 ) );
- 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);
- PlListViewItemDelegate *pl = new PlListViewItemDelegate();
- setItemDelegate( pl );
-
- CONNECT( this, activated( const QModelIndex & ), this, activate( const QModelIndex & ) );
+ setItemDelegate( delegate );
}
-void PlIconView::activate( const QModelIndex & index )
+PlListView::PlListView( PLModel *model, QWidget *parent ) : QListView( parent )
{
- if( model()->hasChildren( index ) )
- setRootIndex( index );
- else
- {
- PLModel *plModel = qobject_cast<PLModel*>( model() );
- if( !plModel ) return;
- plModel->activateItem( index );
- }
+ setModel( model );
+ setViewMode( QListView::ListMode );
+ setUniformItemSizes( true );
+ setSelectionMode( QAbstractItemView::ExtendedSelection );
+ setAlternatingRowColors( true );
+ setDragEnabled(true);
+ setAcceptDrops( true );
+ setDropIndicatorShown(true);
+
+ PlListViewItemDelegate *delegate = new PlListViewItemDelegate( this );
+ setItemDelegate( delegate );
}