PageRenderTime 321ms CodeModel.GetById 116ms app.highlight 95ms RepoModel.GetById 106ms app.codeStats 0ms

/src/libtomahawk/playlist/albumitemdelegate.cpp

http://github.com/tomahawk-player/tomahawk
C++ | 273 lines | 208 code | 45 blank | 20 comment | 39 complexity | c3f2ef97a67ed55af9bb71e1b3d81162 MD5 | raw file
  1/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
  2 *
  3 *   Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
  4 *
  5 *   Tomahawk is free software: you can redistribute it and/or modify
  6 *   it under the terms of the GNU General Public License as published by
  7 *   the Free Software Foundation, either version 3 of the License, or
  8 *   (at your option) any later version.
  9 *
 10 *   Tomahawk is distributed in the hope that it will be useful,
 11 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 13 *   GNU General Public License for more details.
 14 *
 15 *   You should have received a copy of the GNU General Public License
 16 *   along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
 17 */
 18
 19#include "albumitemdelegate.h"
 20
 21#include <QApplication>
 22#include <QPainter>
 23#include <QAbstractItemView>
 24
 25#include "artist.h"
 26#include "query.h"
 27#include "result.h"
 28
 29#include "utils/tomahawkutils.h"
 30#include "utils/logger.h"
 31
 32#include "playlist/albumitem.h"
 33#include "playlist/albumproxymodel.h"
 34#include <QMouseEvent>
 35#include <viewmanager.h>
 36
 37
 38AlbumItemDelegate::AlbumItemDelegate( QAbstractItemView* parent, AlbumProxyModel* proxy )
 39    : QStyledItemDelegate( (QObject*)parent )
 40    , m_view( parent )
 41    , m_model( proxy )
 42{
 43    m_defaultCover = QPixmap( RESPATH "images/no-album-art-placeholder.png" );
 44}
 45
 46
 47QSize
 48AlbumItemDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
 49{
 50    QSize size = QStyledItemDelegate::sizeHint( option, index );
 51    return size;
 52}
 53
 54
 55void
 56AlbumItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
 57{
 58    AlbumItem* item = m_model->sourceModel()->itemFromIndex( m_model->mapToSource( index ) );
 59    if ( !item )
 60        return;
 61
 62    QStyleOptionViewItemV4 opt = option;
 63    initStyleOption( &opt, QModelIndex() );
 64    qApp->style()->drawControl( QStyle::CE_ItemViewItem, &opt, painter );
 65
 66    painter->save();
 67    painter->setRenderHint( QPainter::Antialiasing );
 68
 69    if ( !( option.state & QStyle::State_Selected ) )
 70    {
 71        QRect shadowRect = option.rect.adjusted( 5, 4, -5, -40 );
 72        painter->setPen( QColor( 90, 90, 90 ) );
 73        painter->drawRoundedRect( shadowRect, 0.5, 0.5 );
 74
 75        QPen shadowPen( QColor( 30, 30, 30 ) );
 76        shadowPen.setWidth( 0.4 );
 77        painter->drawLine( shadowRect.bottomLeft() + QPoint( -1, 2 ), shadowRect.bottomRight() + QPoint( 1, 2 ) );
 78
 79        shadowPen.setColor( QColor( 160, 160, 160 ) );
 80        painter->setPen( shadowPen );
 81        painter->drawLine( shadowRect.topLeft() + QPoint( -1, 2 ), shadowRect.bottomLeft() + QPoint( -1, 2 ) );
 82        painter->drawLine( shadowRect.topRight() + QPoint( 2, 2 ), shadowRect.bottomRight() + QPoint( 2, 2 ) );
 83        painter->drawLine( shadowRect.bottomLeft() + QPoint( 0, 3 ), shadowRect.bottomRight() + QPoint( 0, 3 ) );
 84
 85        shadowPen.setColor( QColor( 180, 180, 180 ) );
 86        painter->setPen( shadowPen );
 87        painter->drawLine( shadowRect.topLeft() + QPoint( -2, 3 ), shadowRect.bottomLeft() + QPoint( -2, 1 ) );
 88        painter->drawLine( shadowRect.topRight() + QPoint( 3, 3 ), shadowRect.bottomRight() + QPoint( 3, 1 ) );
 89        painter->drawLine( shadowRect.bottomLeft() + QPoint( 0, 4 ), shadowRect.bottomRight() + QPoint( 0, 4 ) );
 90    }
 91
 92    QPixmap cover;
 93    if ( !item->album().isNull() )
 94    {
 95        cover.loadFromData( item->album()->cover() );
 96    }
 97    else if ( !item->artist().isNull() )
 98    {
 99        cover.loadFromData( item->artist()->cover() );
100    }
101
102    if ( cover.isNull() )
103        cover = m_defaultCover;
104
105    QRect r = option.rect.adjusted( 6, 5, -6, -41 );
106
107    if ( option.state & QStyle::State_Selected )
108    {
109#if defined(Q_WS_MAC) || defined(Q_WS_WIN)
110        painter->save();
111        painter->setRenderHint( QPainter::Antialiasing );
112
113        QPainterPath border;
114        border.addRoundedRect( r.adjusted( -2, -2, 2, 2 ), 3, 3 );
115        QPen borderPen( QColor( 86, 170, 243 ) );
116        borderPen.setWidth( 5 );
117        painter->setPen( borderPen );
118        painter->drawPath( border );
119
120        painter->restore();
121#else
122        opt.palette.setColor( QPalette::Text, opt.palette.color( QPalette::HighlightedText ) );
123#endif
124    }
125
126    QPixmap scover;
127    if ( m_cache.contains( cover.cacheKey() ) )
128    {
129        scover = m_cache.value( cover.cacheKey() );
130    }
131    else
132    {
133        scover = cover.scaled( r.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation );
134        m_cache.insert( cover.cacheKey(), scover );
135    }
136    painter->drawPixmap( r, scover );
137
138    painter->setPen( opt.palette.color( QPalette::Text ) );
139    QTextOption to;
140    to.setWrapMode( QTextOption::NoWrap );
141
142    QString text;
143    QFont font = opt.font;
144    font.setPixelSize( 11 );
145    QFont boldFont = font;
146    boldFont.setBold( true );
147
148    QRect textRect = option.rect.adjusted( 0, option.rect.height() - 32, 0, -2 );
149
150    QString name;
151    if ( !item->album().isNull() )
152        name = item->album()->name();
153    else if ( !item->artist().isNull() )
154        name = item->artist()->name();
155
156    painter->setFont( boldFont );
157    bool oneLiner = false;
158    if ( item->album().isNull() || item->album()->artist().isNull() )
159        oneLiner = true;
160    else
161        oneLiner = ( textRect.height() / 2 < painter->fontMetrics().boundingRect( item->album()->name() ).height() ||
162                     textRect.height() / 2 < painter->fontMetrics().boundingRect( item->album()->artist()->name() ).height() );
163
164    if ( oneLiner )
165    {
166        to.setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
167        text = painter->fontMetrics().elidedText( name, Qt::ElideRight, textRect.width() - 3 );
168        painter->drawText( textRect, text, to );
169    }
170    else
171    {
172        to.setAlignment( Qt::AlignHCenter | Qt::AlignTop );
173        text = painter->fontMetrics().elidedText( item->album()->name(), Qt::ElideRight, textRect.width() - 3 );
174        painter->drawText( textRect, text, to );
175
176        // If the user is hovering over an artist rect, draw a background so she knows it's clickable
177        QRect r = textRect;
178        r.setTop( r.bottom() - painter->fontMetrics().height() );
179        r.adjust( 4, 0, -4, -1 );
180        if ( m_hoveringOver == index )
181        {
182            TomahawkUtils::drawQueryBackground( painter, opt.palette, r, 1.1 );
183            painter->setPen( opt.palette.color( QPalette::HighlightedText ) );
184        }
185        else
186        {
187            if ( !( option.state & QStyle::State_Selected ) )
188#ifdef Q_WS_MAC
189                painter->setPen( opt.palette.color( QPalette::Dark ).darker( 200 ) );
190#else
191                painter->setPen( opt.palette.color( QPalette::Dark ) );
192#endif
193        }
194
195        to.setAlignment( Qt::AlignHCenter | Qt::AlignBottom );
196        text = painter->fontMetrics().elidedText( item->album()->artist()->name(), Qt::ElideRight, textRect.width() - 10 );
197        painter->drawText( textRect.adjusted( 5, -1, -5, -1 ), text, to );
198
199        // Calculate rect of artist on-hover button click area
200        m_artistNameRects[ index ] = r;
201    }
202
203    painter->restore();
204}
205
206
207bool
208AlbumItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index )
209{
210    Q_UNUSED( model );
211    Q_UNUSED( option );
212
213    if ( event->type() != QEvent::MouseButtonRelease &&
214         event->type() != QEvent::MouseMove &&
215         event->type() != QEvent::MouseButtonPress &&
216         event->type() != QEvent::Leave )
217        return false;
218
219    if ( m_artistNameRects.contains( index ) )
220    {
221        QMouseEvent* ev = static_cast< QMouseEvent* >( event );
222        QRect artistNameRect = m_artistNameRects[ index ];
223        if ( artistNameRect.contains( ev->pos() ) )
224        {
225            if ( event->type() == QEvent::MouseMove )
226            {
227                if ( m_hoveringOver != index )
228                {
229                    QModelIndex old = m_hoveringOver;
230                    m_hoveringOver = index;
231                    emit updateIndex( old );
232                    emit updateIndex( index );
233                }
234
235                event->accept();
236                return true;
237            }
238            else if ( event->type() == QEvent::MouseButtonRelease )
239            {
240                AlbumItem* item = m_model->sourceModel()->itemFromIndex( m_model->mapToSource( index ) );
241                if ( !item || item->album().isNull() || item->album()->artist().isNull() )
242                    return false;
243
244                ViewManager::instance()->show( item->album()->artist() );
245
246                event->accept();
247                return true;
248            }
249            else if ( event->type() == QEvent::MouseButtonPress )
250            {
251                // Stop the whole album from having a down click action as we just want the artist name to be clicked
252                event->accept();
253                return true;
254            }
255        }
256    }
257
258    whitespaceMouseEvent();
259
260    return false;
261}
262
263
264void
265AlbumItemDelegate::whitespaceMouseEvent()
266{
267    if ( m_hoveringOver.isValid() )
268    {
269        QModelIndex old = m_hoveringOver;
270        m_hoveringOver = QPersistentModelIndex();
271        emit updateIndex( old );
272    }
273}