]> git.sesse.net Git - vlc/blobdiff - modules/gui/qt4/components/playlist/icon_view.cpp
Qt: respect font sizes
[vlc] / modules / gui / qt4 / components / playlist / icon_view.cpp
index 7e63ebe33e1aeeb57c21a714424153dba55fb5f9..9b8d1f183322df734d558044429b0d1af233729b 100644 (file)
@@ -23,6 +23,7 @@
 
 #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, 0, - 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 ).toInt() );
-    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 );
+    QApplication::style()->drawPrimitive( QStyle::PE_PanelItemViewItem, &option,
+                                          painter );
 
-    // 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();
+    painter->save();
 
-    // Draw the art pix
+    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::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 ) );
 
-    textRect = textRect.adjusted( 0, textRect.height(),
-                                    0, textRect.height() );
-    pixpainter->drawText(  textRect,
-                    fm.elidedText( artist, Qt::ElideRight, textRect.width() ),
-                    QTextOption( Qt::AlignCenter ) );
+    QPixmap artPix = getArtPixmap( index, QSize( LISTVIEW_ART_SIZE, LISTVIEW_ART_SIZE ) );
 
-    delete pixpainter; // Ensure all paint operations have finished
+    //Draw selection rectangle
+    QApplication::style()->drawPrimitive( QStyle::PE_PanelItemViewItem, &option, painter );
 
-    // Here real drawing happens
-    painter->drawPixmap( option.rect, pix );
+    //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 );
+    }
 
-    // Cache the rendering
-    QPixmapCache::insert( key, pix );
+    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
 {
-    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();
-    setItemDelegate( pl );
+    PlListViewItemDelegate *delegate = new PlListViewItemDelegate( this );
+    setItemDelegate( delegate );
 }