Make the playlist use alternating background colors
[amarok.git] / src / playlist / PlaylistGraphicsItem.cpp
blobc3c478a590d6b995342e1f3c1bb84df4a5e0dc63
1 /***************************************************************************
2 * copyright : (C) 2007 Ian Monroe <ian@monroe.nu> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License version 2 *
6 * as published by the Free Software Foundation. *
7 ***************************************************************************/
9 #include "debug.h"
10 #include "meta/MetaUtility.h"
11 #include "PlaylistGraphicsItem.h"
12 #include "PlaylistModel.h"
13 #include "TheInstances.h"
15 #include <QBrush>
16 #include <QFontMetricsF>
17 #include <QGraphicsScene>
18 #include <QGraphicsTextItem>
19 #include <QGraphicsPixmapItem>
20 #include <QGraphicsRectItem>
21 #include <QGraphicsSceneMouseEvent>
22 #include <QGraphicsView>
23 #include <QMimeData>
24 #include <QPen>
25 #include <QRadialGradient>
26 #include <QScrollBar>
27 #include <QStyleOptionGraphicsItem>
29 struct PlaylistNS::GraphicsItem::ActiveItems
31 ActiveItems()
32 : topLeftText( 0 )
33 , bottomLeftText( 0 )
34 , topRightText( 0 )
35 , bottomRightText( 0 )
36 , background( 0 )
37 , foreground( 0 )
38 , lastWidth( -5 )
39 { }
40 ~ActiveItems()
42 delete albumArt;
43 delete topLeftText;
44 delete bottomLeftText;
45 delete topRightText;
46 delete bottomRightText;
47 delete background;
48 delete foreground;
50 QGraphicsPixmapItem* albumArt;
51 QGraphicsTextItem* topLeftText;
52 QGraphicsTextItem* bottomLeftText;
53 QGraphicsTextItem* topRightText;
54 QGraphicsTextItem* bottomRightText;
55 QGraphicsRectItem* background;
56 QGraphicsRectItem* foreground;
57 int lastWidth;
58 Meta::TrackPtr track;
61 const qreal PlaylistNS::GraphicsItem::ALBUM_WIDTH = 50.0;
62 const qreal PlaylistNS::GraphicsItem::MARGIN = 2.0;
63 qreal PlaylistNS::GraphicsItem::s_height = -1.0;
64 QFontMetricsF* PlaylistNS::GraphicsItem::s_fm = 0;
66 PlaylistNS::GraphicsItem::GraphicsItem()
67 : QGraphicsItem()
68 , m_items( 0 )
69 , m_track( 0 )
70 , m_verticalOffset( 2.0 )
72 if( not s_fm )
74 s_fm = new QFontMetricsF( QFont() );
75 s_height = qMax( ALBUM_WIDTH, s_fm->height() * 2 ) + 2 * m_verticalOffset;
77 // setHandlesChildEvents( true );
78 setFlag( QGraphicsItem::ItemIsSelectable );
79 setAcceptDrops( true );
82 PlaylistNS::GraphicsItem::~GraphicsItem()
84 delete m_items;
87 void
88 PlaylistNS::GraphicsItem::paint( QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget )
90 Q_UNUSED( painter ); Q_UNUSED( widget );
91 const int row = getRow();
92 const QModelIndex index = The::playlistModel()->index( row, 0 );
94 if( not m_items || ( option->rect.width() != m_items->lastWidth ) )
97 if( not m_items )
99 const Meta::TrackPtr track = index.data( ItemRole ).value< PlaylistNS::Item* >()->track();
100 m_items = new PlaylistNS::GraphicsItem::ActiveItems();
101 m_items->track = track;
102 init( track );
104 resize( m_items->track, option->rect.width() );
107 if( not m_items->background )
109 m_items->background = new QGraphicsRectItem( option->rect, this );
110 m_items->background->setPos( 0.0, 0.0 );
111 m_items->background->setPen( QPen( Qt::NoPen ) );
112 m_items->background->setBrush( option->palette.highlight() );
113 m_items->background->setZValue( -5.0 );
117 if( option->state & QStyle::State_Selected )
119 m_items->background->setBrush( option->palette.highlight() );
120 m_items->background->show();
122 else
124 //alternate color of background
125 if ( row % 2 )
126 m_items->background->setBrush( option->palette.base() );
127 else
128 m_items->background->setBrush( option->palette.alternateBase() );
130 m_items->background->show();
133 if( index.data( ActiveTrackRole ).toBool() )
135 if( not m_items->foreground )
137 m_items->foreground = new QGraphicsRectItem( option->rect, this );
138 m_items->foreground->setPos( 0.0, m_verticalOffset );
139 m_items->foreground->setZValue( 5.0 );
140 QRadialGradient gradient(option->rect.width() / 2.0, option->rect.height() / 2.0, option->rect.width() / 2.0, 20 + option->rect.width() / 2.0, option->rect.height() / 2.0 );
141 QColor start = option->palette.highlight().color().light();
142 start.setAlpha( 51 );
143 QColor end = option->palette.highlight().color().dark();
144 end.setAlpha( 51 );
145 gradient.setColorAt( 0.0, start );
146 gradient.setColorAt( 1.0, end );
147 QBrush brush( gradient );
148 m_items->foreground->setBrush( brush );
149 m_items->foreground->setPen( QPen( Qt::NoPen ) );
151 else
152 m_items->background->hide();
153 m_items->foreground->show();
155 else if( m_items->foreground )
156 m_items->foreground->hide();
158 m_items->albumArt->show();
161 void
162 PlaylistNS::GraphicsItem::init( Meta::TrackPtr track )
164 m_track = track;
166 QPixmap albumPixmap;
167 if( track->album() )
168 albumPixmap = track->album()->image( int( ALBUM_WIDTH ) );
170 m_items->albumArt = new QGraphicsPixmapItem( albumPixmap, this );
171 m_items->albumArt->setPos( 0.0, m_verticalOffset );
174 QFont font;
175 font.setPointSize( font.pointSize() - 1 );
176 #define NewText( X ) \
177 X = new QGraphicsTextItem( this ); \
178 X->setTextInteractionFlags( Qt::TextEditorInteraction ); \
179 X->setFont( font );
180 NewText( m_items->topLeftText )
181 NewText( m_items->bottomLeftText )
182 NewText( m_items->topRightText )
183 NewText( m_items->bottomRightText )
184 #undef NewText
188 void
189 PlaylistNS::GraphicsItem::resize( Meta::TrackPtr track, int totalWidth )
191 if( totalWidth == -1 || totalWidth == m_items->lastWidth ) //no change needed
192 return;
193 if( m_items->lastWidth != -5 ) //this isn't the first "resize"
194 prepareGeometryChange();
195 m_items->lastWidth = totalWidth;
196 QString prettyLength = Meta::secToPrettyTime( track->length() );
197 QString album;
198 if( track->album() )
199 album = track->album()->name();
201 const qreal lineTwoY = s_height / 2 + m_verticalOffset;
202 const qreal textWidth = ( ( qreal( totalWidth ) - ALBUM_WIDTH ) / 2.0 );
203 const qreal leftAlignX = ALBUM_WIDTH + MARGIN;
204 qreal rightAlignX;
206 qreal middle = textWidth + ALBUM_WIDTH + ( MARGIN * 2.0 );
207 qreal rightWidth = totalWidth - qMax( s_fm->width( album )
208 , s_fm->width( prettyLength ) );
209 rightAlignX = qMax( middle, rightWidth );
211 m_items->topRightText->setPos( rightAlignX, m_verticalOffset );
212 m_items->bottomRightText->setPos( rightAlignX, lineTwoY );
213 m_items->topRightText->setPlainText( s_fm->elidedText( album, Qt::ElideRight, totalWidth - rightAlignX ) );
214 m_items->bottomRightText->setPlainText( s_fm->elidedText( prettyLength, Qt::ElideRight, totalWidth - rightAlignX ) );
217 qreal spaceForLeft = totalWidth - ( totalWidth - rightAlignX ) - leftAlignX;
219 QString artist;
220 if( track->artist() )
221 artist = track->artist()->name();
222 m_items->topLeftText->setPlainText( s_fm->elidedText( artist, Qt::ElideRight, spaceForLeft ) );
223 m_items->topLeftText->setPos( leftAlignX, m_verticalOffset );
226 m_items->bottomLeftText->setPlainText( s_fm->elidedText( QString("%1 - %2").arg( QString::number( track->trackNumber() ), track->name() )
227 , Qt::ElideRight, spaceForLeft ) );
228 m_items->bottomLeftText->setPos( leftAlignX, lineTwoY );
231 QRectF
232 PlaylistNS::GraphicsItem::boundingRect() const
234 // the viewport()->size() takes scrollbars into account
235 return QRectF( 0.0, 0.0, scene()->views().at(0)->viewport()->size().width(), s_height );
238 void
239 PlaylistNS::GraphicsItem::mouseDoubleClickEvent( QGraphicsSceneMouseEvent* event )
241 if( m_items )
243 The::playlistModel()->play( getRow() );
244 event->accept();
245 return;
247 QGraphicsItem::mouseDoubleClickEvent( event );
250 void
251 PlaylistNS::GraphicsItem::dragEnterEvent( QGraphicsSceneDragDropEvent *event )
253 foreach( QString mime, The::playlistModel()->mimeTypes() )
254 if( event->mimeData()->hasFormat( mime ) )
255 event->accept();
258 void
259 PlaylistNS::GraphicsItem::dropEvent( QGraphicsSceneDragDropEvent * event )
261 The::playlistModel()->dropMimeData( event->mimeData(), Qt::CopyAction, getRow(), 0, QModelIndex() );
264 void
265 PlaylistNS::GraphicsItem::refresh()
267 QPixmap albumPixmap;
268 if ( ! m_track )
269 return;
271 if( m_track->album() )
272 albumPixmap = m_track->album()->image( int( ALBUM_WIDTH ) );
274 m_items->albumArt->hide();
275 delete ( m_items->albumArt );
276 m_items->albumArt = new QGraphicsPixmapItem( albumPixmap, this );
277 m_items->albumArt->setPos( 0.0, m_verticalOffset );