1 /***************************************************************************
2 * copyright : (C) 2007 Ian Monroe <ian@monroe.nu>
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License or (at your option) version 3 or any later version
8 * accepted by the membership of KDE e.V. (or its successor approved
9 * by the membership of KDE e.V.), which shall act as a proxy
10 * defined in Section 14 of version 3 of the license.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **************************************************************************/
23 #include "meta/MetaUtility.h"
24 #include "AmarokMimeData.h"
25 #include "PlaylistGraphicsItem.h"
26 #include "PlaylistGraphicsView.h"
27 #include "PlaylistDropVis.h"
28 #include "PlaylistModel.h"
29 #include "PlaylistTextItem.h"
30 #include "TheInstances.h"
31 #include "CoverManager.h"
33 #include "KStandardDirs"
37 #include <QFontMetricsF>
38 #include <QGraphicsScene>
39 #include <QGraphicsTextItem>
40 #include <QGraphicsPixmapItem>
41 #include <QGraphicsRectItem>
42 #include <QGraphicsSceneMouseEvent>
43 #include <QGraphicsView>
46 #include <QPixmapCache>
47 #include <QRadialGradient>
49 #include <QStyleOptionGraphicsItem>
53 struct Playlist::GraphicsItem::ActiveItems
58 , bottomRightText( 0 )
68 delete bottomLeftText
;
69 delete bottomRightText
;
76 QGraphicsPixmapItem
* foreground
;
77 Playlist::TextItem
* bottomLeftText
;
78 Playlist::TextItem
* bottomRightText
;
79 Playlist::TextItem
* topLeftText
;
80 Playlist::TextItem
* topRightText
;
82 QColor overlayGradientStart
;
83 QColor overlayGradientEnd
;
89 QRectF preDragLocation
;
94 const qreal
Playlist::GraphicsItem::ALBUM_WIDTH
= 50.0;
95 const qreal
Playlist::GraphicsItem::MARGIN
= 4.0;
96 QFontMetricsF
* Playlist::GraphicsItem::s_fm
= 0;
97 QSvgRenderer
* Playlist::GraphicsItem::s_svgRenderer
= 0;
100 Playlist::GraphicsItem::GraphicsItem()
105 , m_groupModeChanged ( false )
106 , m_collapsible ( true )
107 , m_dataChanged( false )
112 s_fm
= new QFontMetricsF( QFont() );
113 m_height
= qMax( ALBUM_WIDTH
, s_fm
->height() * 2 ) + 2 * MARGIN
;
116 if ( !s_svgRenderer
) {
117 s_svgRenderer
= new QSvgRenderer( KStandardDirs::locate( "data","amarok/images/playlist_items.svg" ));
118 if ( ! s_svgRenderer
->isValid() )
119 debug() << "svg is kaputski";
122 setFlag( QGraphicsItem::ItemIsSelectable
);
123 setFlag( QGraphicsItem::ItemIsMovable
);
124 setAcceptDrops( true );
125 // setHandlesChildEvents( true ); // don't let drops etc hit the text items, doing stupid things
128 Playlist::GraphicsItem::~GraphicsItem()
134 Playlist::GraphicsItem::paint( QPainter
* painter
, const QStyleOptionGraphicsItem
* option
, QWidget
* widget
)
137 // 1) You do not talk about ::paint method
138 // 2) You DO NOT talk about ::paint method
139 // 3) Do not show or hide item that are already shown or hidden, respectively
140 // 4) Do not setBrush without making sure its hasn't already been set to that brush().
141 // 5) ::paint RULES apply to all methods called from ::paint as well ( duh! )
142 // 6) If this is your first night at ::paint method, you HAVE to paint.
143 Q_UNUSED( painter
); Q_UNUSED( widget
);
145 //debug() << "painting row: " << m_currentRow;
146 const QModelIndex index
= The::playlistModel()->index( m_currentRow
, 0 );
148 if( m_dataChanged
|| !m_items
|| ( option
->rect
.width() != m_items
->lastWidth
) || m_groupModeChanged
)
153 const Meta::TrackPtr track
= index
.data( ItemRole
).value
< Playlist::Item
* >()->track();
154 m_items
= new Playlist::GraphicsItem::ActiveItems();
155 m_items
->track
= track
;
158 m_groupModeChanged
= false;
159 resize( m_items
->track
, option
->rect
.width() );
162 bool isActiveTrack
= index
.data( ActiveTrackRole
).toBool();
165 // call paint method based on type
166 if ( m_groupMode
== None
) {
167 paintSingleTrack( painter
, option
, isActiveTrack
);
168 } else if ( m_groupMode
== Head
) {
169 paintHead( painter
, option
, isActiveTrack
);
170 } else if ( m_groupMode
== Head_Collapsed
) {
171 paintCollapsedHead( painter
, option
, isActiveTrack
);
172 } else if ( m_groupMode
== Body
) {
173 paintBody( painter
, option
, isActiveTrack
, index
.data( GroupedAlternateRole
).toBool() );
174 } else if ( m_groupMode
== End
) {
175 paintTail( painter
, option
, isActiveTrack
, index
.data( GroupedAlternateRole
).toBool() );
176 } else if ( m_groupMode
== Collapsed
) {
185 Playlist::GraphicsItem::init( Meta::TrackPtr track
)
189 font
.setPointSize( font
.pointSize() - 1 );
190 #define NewText( X ) \
191 X = new Playlist::TextItem( this ); \
192 X->setTextInteractionFlags( Qt::TextEditorInteraction ); \
194 NewText( m_items
->topLeftText
)
195 NewText( m_items
->bottomLeftText
)
196 NewText( m_items
->topRightText
)
197 NewText( m_items
->bottomRightText
)
202 Playlist::GraphicsItem::resize( Meta::TrackPtr track
, int totalWidth
)
204 if( totalWidth
== -1 /*|| totalWidth == m_items->lastWidth */) //no change needed
206 if( m_items
->lastWidth
!= -5 ) //this isn't the first "resize"
207 prepareGeometryChange();
208 m_items
->lastWidth
= totalWidth
;
210 QString prettyLength
;
212 if ( m_groupMode
== Head_Collapsed
)
215 for( int i
= m_currentRow
; i
< m_currentRow
+ m_items
->groupedTracks
; i
++ )
216 seconds
+= The::playlistModel()->itemList()[ i
]->track()->length();
217 prettyLength
= Meta::secToPrettyTime( seconds
);
220 prettyLength
= Meta::secToPrettyTime( track
->length() );
224 album
= track
->album()->name();
226 const qreal lineTwoY
= m_height
/ 2 + MARGIN
;
227 const qreal textWidth
= ( ( qreal( totalWidth
) - ALBUM_WIDTH
) / 2.0 );
228 const qreal leftAlignX
= ALBUM_WIDTH
+ MARGIN
;
229 qreal topRightAlignX
;
230 qreal bottomRightAlignX
;
233 qreal middle
= textWidth
+ ALBUM_WIDTH
+ ( MARGIN
* 2.0 );
234 qreal rightWidth
= totalWidth
- qMax( s_fm
->width( album
)
235 , s_fm
->width( prettyLength
) );
236 topRightAlignX
= qMax( middle
, rightWidth
);
239 //lets use all the horizontal space we can get for now..
240 int lengthStringWidth
= (int)(s_fm
->width( prettyLength
));
241 bottomRightAlignX
= ( totalWidth
- 4 * MARGIN
) - lengthStringWidth
;
246 qreal spaceForTopLeft
= totalWidth
- ( totalWidth
- topRightAlignX
) - leftAlignX
;
247 qreal spaceForBottomLeft
= totalWidth
- ( totalWidth
- bottomRightAlignX
) - leftAlignX
;
249 if ( m_groupMode
== Head_Collapsed
) {
251 m_items
->bottomLeftText
->setEditableText( QString("%1 tracks").arg( QString::number( m_items
->groupedTracks
) ) , spaceForBottomLeft
);
252 QFont f
= m_items
->bottomLeftText
->font();
254 m_items
->bottomLeftText
->setFont( f
);
255 m_items
->bottomRightText
->setEditableText( prettyLength
, totalWidth
- bottomRightAlignX
);
258 m_items
->bottomLeftText
->setFont( m_items
->bottomRightText
->font() );
259 m_items
->bottomLeftText
->setEditableText( QString("%1 - %2").arg( QString::number( track
->trackNumber() ), track
->name() ) , spaceForBottomLeft
);
260 m_items
->bottomRightText
->setEditableText( prettyLength
, totalWidth
- bottomRightAlignX
);
262 if ( m_groupMode
== None
) {
264 m_items
->topRightText
->setPos( topRightAlignX
, MARGIN
);
265 m_items
->topRightText
->setEditableText( album
, totalWidth
- topRightAlignX
);
269 if( track
->artist() )
270 artist
= track
->artist()->name();
271 m_items
->topLeftText
->setEditableText( artist
, spaceForTopLeft
);
272 m_items
->topLeftText
->setPos( leftAlignX
, MARGIN
);
275 m_items
->bottomLeftText
->setPos( leftAlignX
, lineTwoY
);
276 m_items
->bottomRightText
->setPos( bottomRightAlignX
, lineTwoY
);
277 } else if ( ( m_groupMode
== Head
) || ( m_groupMode
== Head_Collapsed
) ) {
279 int headingCenter
= (int)( MARGIN
+ ( ALBUM_WIDTH
- s_fm
->height()) / 2 );
281 m_items
->topRightText
->setPos( topRightAlignX
, headingCenter
);
282 m_items
->topRightText
->setEditableText( album
, totalWidth
- topRightAlignX
);
286 //various artist handling:
287 //if the album has no albumartist, use Various Artists, otherwise use the albumartist's name
288 if( track
->album()->albumArtist() )
289 artist
= track
->album()->albumArtist()->name();
292 artist
= findArtistForCurrentAlbum();
293 if( artist
.isEmpty() )
294 artist
= i18n( "Various Artists" );
296 m_items
->topLeftText
->setEditableText( artist
, spaceForTopLeft
);
297 m_items
->topLeftText
->setPos( leftAlignX
, headingCenter
);
300 int underImageY
= (int)( MARGIN
+ ALBUM_WIDTH
+ 6 );
302 m_items
->bottomLeftText
->setPos( MARGIN
* 3, underImageY
);
303 m_items
->bottomRightText
->setPos( bottomRightAlignX
, underImageY
);
306 m_items
->bottomLeftText
->setPos( MARGIN
* 3, 0 );
307 m_items
->bottomRightText
->setPos( bottomRightAlignX
, 0 );
310 //make sure the activ eitem overlay has the correct width
314 if( m_items
->foreground
)
318 if ( ( m_groupMode
== Head
) || ( m_groupMode
== Head_Collapsed
) ) {
319 trackRect
= QRectF( 0, ALBUM_WIDTH
+ 2 * MARGIN
, totalWidth
, s_fm
->height() /*+ MARGIN*/ );
321 trackRect
= QRectF( 0, 0, totalWidth
, m_height
);
322 if ( ( m_groupMode
!= Body
) && !( ( m_groupMode
== Head
) ) )
323 trackRect
.setHeight( trackRect
.height() - 2 ); // add a little space between items
326 debug() << "Resizing active track overlay";
328 QString key
= QString("active_overlay:%1x%2").arg(trackRect
.width()).arg(trackRect
.height());
330 QPixmap
background( (int)( trackRect
.width() ), (int)( trackRect
.height() ) );
331 background
.fill( Qt::transparent
);
334 if (!QPixmapCache::find(key
, background
)) {
335 QPainter
pt( &background
);
336 s_svgRenderer
->render( &pt
, "active_overlay", QRectF( 0, 0, trackRect
.width(), trackRect
.height() ) );
337 QPixmapCache::insert(key
, background
);
339 m_items
->foreground
->setPixmap( background
);
340 m_items
->foreground
->setZValue( 10.0 );
346 m_items
->lastWidth
= totalWidth
;
350 Playlist::GraphicsItem::findArtistForCurrentAlbum() const
352 if( !( ( m_groupMode
== Head
) || ( m_groupMode
== Head_Collapsed
) ) )
355 const QModelIndex index
= The::playlistModel()->index( m_currentRow
, 0 );
356 if( ! ( ( index
.data( GroupRole
).toInt() == Head
) || ( index
.data( GroupRole
).toInt() == Head_Collapsed
) ) )
363 Meta::TrackPtr currentTrack
= index
.data( TrackRole
).value
< Meta::TrackPtr
>();
364 if( currentTrack
->artist() )
365 artist
= currentTrack
->artist()->name();
368 //it's an album group, and the current row is the head, so the next row is either Body or End
369 //that means we have to execute the loop at least once
371 int row
= m_currentRow
+ 1;
374 idx
= The::playlistModel()->index( row
++, 0 );
375 Meta::TrackPtr track
= idx
.data( TrackRole
).value
< Meta::TrackPtr
>();
376 if( track
->artist() )
378 if( artist
!= track
->artist()->name() )
386 while( idx
.data( GroupRole
).toInt() == Body
);
393 Playlist::GraphicsItem::boundingRect() const
395 // the viewport()->size() takes scrollbars into account
396 return QRectF( 0.0, 0.0, The::playlistView()->viewport()->size().width(), m_height
);
400 Playlist::GraphicsItem::play()
402 The::playlistModel()->play( m_currentRow
);
406 Playlist::GraphicsItem::showImage() const
408 ( new CoverViewDialog( m_items
->track
->album(), The::playlistView() ) )->show();
412 Playlist::GraphicsItem::fetchImage()
414 CoverFetcher
*fetcher
= The::coverFetcher();
415 fetcher
->manualFetch( m_items
->track
->album() );
419 Playlist::GraphicsItem::unsetImage()
421 m_items
->track
->album()->removeImage();
425 Playlist::GraphicsItem::dataChanged()
427 m_dataChanged
= true;
431 Playlist::GraphicsItem::hasImage() const
433 return m_items
->track
->album()->hasImage();
437 Playlist::GraphicsItem::mouseDoubleClickEvent( QGraphicsSceneMouseEvent
*event
)
445 QGraphicsItem::mouseDoubleClickEvent( event
);
449 Playlist::GraphicsItem::mousePressEvent( QGraphicsSceneMouseEvent
*event
)
451 if( event
->buttons() & Qt::RightButton
|| !m_items
)
456 m_items
->preDragLocation
= mapToScene( boundingRect() ).boundingRect();
458 //did we hit the collapse / expand button?
461 QRectF
rect( boundingRect().width() - ( 16 + MARGIN
), MARGIN
, 16, 16 );
462 if( rect
.contains( event
->pos() ) )
464 if ( m_groupMode
== Head_Collapsed
)
465 The::playlistModel()->setCollapsed( m_currentRow
, false );
466 else if ( m_groupMode
== Head
)
467 The::playlistModel()->setCollapsed( m_currentRow
, true );
471 QGraphicsItem::mousePressEvent( event
);
474 // With help from QGraphicsView::mouseMoveEvent()
476 Playlist::GraphicsItem::mouseMoveEvent( QGraphicsSceneMouseEvent
*event
)
478 if( (event
->buttons() & Qt::LeftButton
) && ( flags() & QGraphicsItem::ItemIsMovable
) && m_items
)
480 QPointF scenePosition
= event
->scenePos();
482 if( scenePosition
.y() < 0 )
485 bool dragOverOriginalPosition
= m_items
->preDragLocation
.contains( scenePosition
);
487 //make sure item is drawn on top of other items
490 // Determine the list of selected items
491 QList
<QGraphicsItem
*> selectedItems
= scene()->selectedItems();
493 selectedItems
<< this;
494 // Move all selected items
495 foreach( QGraphicsItem
*item
, selectedItems
)
497 if( (item
->flags() & QGraphicsItem::ItemIsMovable
) && (!item
->parentItem() || !item
->parentItem()->isSelected()) )
499 Playlist::GraphicsItem
*above
= 0;
501 if( item
== this && !dragOverOriginalPosition
)
503 diff
= event
->scenePos() - event
->lastScenePos();
504 QList
<QGraphicsItem
*> collisions
= scene()->items( event
->scenePos() );
505 foreach( QGraphicsItem
*i
, collisions
)
507 Playlist::GraphicsItem
*c
= dynamic_cast<Playlist::GraphicsItem
*>( i
);
517 diff
= item
->mapToParent( item
->mapFromScene(event
->scenePos()))
518 - item
->mapToParent(item
->mapFromScene(event
->lastScenePos()));
521 item
->moveBy( 0, diff
.y() );
522 if( item
->flags() & ItemIsSelectable
)
523 item
->setSelected( true );
525 if( dragOverOriginalPosition
)
526 Playlist::DropVis::instance()->show( m_items
->preDragLocation
.y() );
528 Playlist::DropVis::instance()->show( above
);
534 QGraphicsItem::mouseMoveEvent( event
);
539 Playlist::GraphicsItem::dragEnterEvent( QGraphicsSceneDragDropEvent
*event
)
541 foreach( const QString
&mime
, The::playlistModel()->mimeTypes() )
543 if( event
->mimeData()->hasFormat( mime
) )
546 Playlist::DropVis::instance()->show( this );
553 Playlist::GraphicsItem::dropEvent( QGraphicsSceneDragDropEvent
* event
)
557 The::playlistModel()->dropMimeData( event
->mimeData(), Qt::CopyAction
, m_currentRow
, 0, QModelIndex() );
558 Playlist::DropVis::instance()->hide();
562 Playlist::GraphicsItem::refresh()
565 if( !m_items
|| !m_items
->track
)
568 if( m_items
->track
->album() )
570 if( !m_items
->track
->album()->hasImage( int(ALBUM_WIDTH
) ) )
572 The::coverFetcher()->queueAlbum( m_items
->track
->album() );
574 albumPixmap
= m_items
->track
->album()->image( int( ALBUM_WIDTH
) );
577 //m_items->albumArt->hide();
578 //delete ( m_items->albumArt );
579 //m_items->albumArt = new QGraphicsPixmapItem( albumPixmap, this );
580 //m_items->albumArt->setPos( 0.0, MARGIN );
583 void Playlist::GraphicsItem::mouseReleaseEvent( QGraphicsSceneMouseEvent
*event
)
585 bool dragOverOriginalPosition
= m_items
->preDragLocation
.contains( event
->scenePos() );
586 if( dragOverOriginalPosition
)
588 setPos( m_items
->preDragLocation
.topLeft() );
589 Playlist::DropVis::instance()->hide();
593 Playlist::GraphicsItem
*above
= 0;
594 QList
<QGraphicsItem
*> collisions
= scene()->items( event
->scenePos() );
595 foreach( QGraphicsItem
*i
, collisions
)
597 Playlist::GraphicsItem
*c
= dynamic_cast<Playlist::GraphicsItem
*>( i
);
604 // if we've dropped ourself ontop of another item, then we need to shuffle the tracks below down
607 setPos( above
->pos() );
608 The::playlistView()->moveItem( this, above
);
610 //Don't just drop item into the void, make it the last item!
612 The::playlistView()->moveItem( this, 0 );
613 //setPos( above->pos() );
614 //The::playlistView()->moveItem( this, above );
618 //make sure item resets its z value
620 Playlist::DropVis::instance()->hide();
623 void Playlist::GraphicsItem::setRow(int row
)
628 const QModelIndex index
= The::playlistModel()->index( m_currentRow
, 0 );
630 //figure out our group state and set height accordingly
631 int currentGroupState
= index
.data( GroupRole
).toInt();
633 if ( currentGroupState
!= m_groupMode
) {
635 debug() << "Group changed for row " << row
;
637 prepareGeometryChange();
640 m_groupMode
= currentGroupState
;
641 m_groupModeChanged
= true;
643 switch ( m_groupMode
) {
647 m_height
= qMax( ALBUM_WIDTH
, s_fm
->height() * 2 ) + 2 * MARGIN
+ 2;
651 m_height
= qMax( ALBUM_WIDTH
, s_fm
->height() * 2 ) + MARGIN
+ s_fm
->height() + 6;
654 debug() << "Collapsed head";
655 m_height
= qMax( ALBUM_WIDTH
, s_fm
->height() * 2 ) + MARGIN
+ s_fm
->height() + 10;
657 const Meta::TrackPtr track
= index
.data( ItemRole
).value
< Playlist::Item
* >()->track();
658 m_items
= new Playlist::GraphicsItem::ActiveItems();
659 m_items
->track
= track
;
662 m_items
->groupedTracks
= index
.data( GroupedTracksRole
).toInt();
666 m_height
= s_fm
->height()/*+ 2 * MARGIN*/;
670 m_height
= s_fm
->height() + 6 /*+ 2 * MARGIN*/;
673 debug() << "Collapsed";
677 debug() << "ERROR!!??";
682 void Playlist::GraphicsItem::hoverEnterEvent( QGraphicsSceneHoverEvent
*event
)
687 /*if ( m_groupMode == Head_Collapsed )
688 The::playlistModel()->setCollapsed( m_currentRow, false ); */
691 void Playlist::GraphicsItem::paintSingleTrack( QPainter
* painter
, const QStyleOptionGraphicsItem
* option
, bool active
)
695 QRectF trackRect
= option
->rect
;
696 painter
->drawPixmap( 0, 0, getCachedSvg( "track", trackRect
.width(), trackRect
.height() ) );
700 if( m_items
->track
->album() )
702 if( !m_items
->track
->album()->hasImage( int( ALBUM_WIDTH
) ) )
704 The::coverFetcher()->queueAlbum( m_items
->track
->album() );
706 albumPixmap
= m_items
->track
->album()->image( int( ALBUM_WIDTH
) );
708 painter
->drawPixmap( imageLocation(), albumPixmap
, QRectF( albumPixmap
.rect() ) );
709 //and make sure the top text elements are shown
710 if( !m_items
->topRightText
->isVisible() )
711 m_items
->topRightText
->show();
712 if( !m_items
->topLeftText
->isVisible() )
713 m_items
->topLeftText
->show();
716 //set selection marker if needed
717 if( option
->state
& QStyle::State_Selected
)
719 painter
->drawPixmap( 2, (int)trackRect
.top(), getCachedSvg( "selection_left", 40, trackRect
.height() ) );
720 painter
->drawPixmap( (int)trackRect
.width() - 42, (int)trackRect
.top(), getCachedSvg( "selection_right", 40, trackRect
.height() ) );
724 //set overlay if item is active:
725 handleActiveOverlay( trackRect
, active
);
729 void Playlist::GraphicsItem::paintHead( QPainter
* painter
, const QStyleOptionGraphicsItem
* option
, bool active
)
731 QRectF trackRect
= QRectF( option
->rect
.x(), ALBUM_WIDTH
+ 2 * MARGIN
, option
->rect
.width(), s_fm
->height() /*+ MARGIN*/ );
732 QRectF headRect
= option
->rect
;
734 painter
->drawPixmap( 0, 0, getCachedSvg( "head", headRect
.width(), headRect
.height() ) );
737 //paint collapse button
738 QString collapseString
;
739 if ( m_groupMode
== Head
)
742 collapseString
= "collapse_button";
744 collapseString
= "collapse_button_grayed_out";
747 collapseString
= "expand_button";
749 painter
->drawPixmap( (int)( option
->rect
.width() - ( 16 + MARGIN
) ), (int)MARGIN
, getCachedSvg( collapseString
, 16, 16 ) );
754 if( m_items
->track
->album() )
756 if( !m_items
->track
->album()->hasImage( int( ALBUM_WIDTH
) ) )
758 The::coverFetcher()->queueAlbum( m_items
->track
->album() );
760 albumPixmap
= m_items
->track
->album()->image( int( ALBUM_WIDTH
) );
762 painter
->drawPixmap( imageLocation(), albumPixmap
, QRectF( albumPixmap
.rect() ) );
763 //and make sure the top text elements are shown
764 if( !m_items
->topRightText
->isVisible() )
765 m_items
->topRightText
->show();
766 if( !m_items
->topLeftText
->isVisible() )
767 m_items
->topLeftText
->show();
770 //set selection marker if needed
771 if( option
->state
& QStyle::State_Selected
)
773 painter
->drawPixmap( 2, (int)trackRect
.top() + 2, getCachedSvg( "selection_left", 40, trackRect
.height() ) );
774 painter
->drawPixmap( (int)trackRect
.width() - 42, (int)trackRect
.top() + 2, getCachedSvg( "selection_right", 40, trackRect
.height() ) );
777 //set overlay if item is active:
778 handleActiveOverlay( trackRect
, active
);
782 void Playlist::GraphicsItem::paintCollapsedHead( QPainter
* painter
, const QStyleOptionGraphicsItem
* option
, bool active
)
784 QRectF trackRect
= QRectF( option
->rect
.x(), ALBUM_WIDTH
+ 2 * MARGIN
, option
->rect
.width(), s_fm
->height() /*+ MARGIN*/ );
785 QRectF headRect
= QRectF( option
->rect
.x(), option
->rect
.y(), option
->rect
.width(), option
->rect
.height() - 2 );
788 painter
->drawPixmap( 0, 0, getCachedSvg( "collapsed_head", headRect
.width(), headRect
.height() ) );
790 //paint collapse button
791 QString collapseString
;
792 if ( m_groupMode
== Head
)
795 collapseString
= "collapse_button";
797 collapseString
= "collapse_button_grayed_out";
800 collapseString
= "expand_button";
802 painter
->drawPixmap( (int)( option
->rect
.width() - ( 16 + MARGIN
) ), (int)MARGIN
, getCachedSvg( collapseString
, 16, 16 ) );
806 if( m_items
->track
->album() )
808 if( !m_items
->track
->album()->hasImage( int( ALBUM_WIDTH
) ) )
810 The::coverFetcher()->queueAlbum( m_items
->track
->album() );
812 albumPixmap
= m_items
->track
->album()->image( int( ALBUM_WIDTH
) );
814 painter
->drawPixmap( imageLocation(), albumPixmap
, QRectF( albumPixmap
.rect() ) );
815 //and make sure the top text elements are shown
816 if( !m_items
->topRightText
->isVisible() )
817 m_items
->topRightText
->show();
818 if( !m_items
->topLeftText
->isVisible() )
819 m_items
->topLeftText
->show();
821 //set selection marker if needed
822 if( option
->state
& QStyle::State_Selected
)
824 painter
->drawPixmap( 2, (int)trackRect
.top(), getCachedSvg( "selection_left", 40, trackRect
.height() ) );
825 painter
->drawPixmap( (int)trackRect
.width() - 42, (int)trackRect
.top(), getCachedSvg( "selection_right", 40, trackRect
.height() ) );
828 //set overlay if item is active
829 handleActiveOverlay( trackRect
, active
);
833 void Playlist::GraphicsItem::paintBody( QPainter
* painter
, const QStyleOptionGraphicsItem
* option
, bool active
, bool alternate
)
835 QRectF trackRect
= option
->rect
;
837 painter
->drawPixmap( 0, 0, getCachedSvg( "body", trackRect
.width(), trackRect
.height() ) );
840 //draw alternate background if needed
842 painter
->drawPixmap( 5, 0, getCachedSvg( "body_background", trackRect
.width() - 10, trackRect
.height() ) );
844 //make sure that the top text items are not shown
845 if( m_items
->topRightText
->isVisible() )
846 m_items
->topRightText
->hide();
847 if( m_items
->topLeftText
->isVisible() )
848 m_items
->topLeftText
->hide();
849 if( !m_items
->bottomRightText
->isVisible() )
850 m_items
->bottomRightText
->show();
851 if( !m_items
->bottomLeftText
->isVisible() )
852 m_items
->bottomLeftText
->show();
854 //set selection marker if needed
855 if( option
->state
& QStyle::State_Selected
)
858 painter
->drawPixmap( 2, (int)trackRect
.top(), getCachedSvg( "selection_left", 40, trackRect
.height() ) );
859 painter
->drawPixmap( (int)trackRect
.width() - 42, (int)trackRect
.top(), getCachedSvg( "selection_right", 40, trackRect
.height() ) );
862 //set overlay if item is active
863 handleActiveOverlay( trackRect
, active
);
868 void Playlist::GraphicsItem::paintTail( QPainter
* painter
, const QStyleOptionGraphicsItem
* option
, bool active
, bool alternate
)
870 QRectF trackRect
= option
->rect
;
871 trackRect
.setHeight( trackRect
.height() - 2 ); // add a little space between items
873 painter
->drawPixmap( 0, 0, getCachedSvg( "tail", trackRect
.width(), trackRect
.height() ) );
878 QRectF tempRect
= trackRect
;
879 tempRect
.setWidth( tempRect
.width() - 10 );
880 tempRect
.setHeight( tempRect
.height() - 4 );
881 painter
->drawPixmap( 5, 0, getCachedSvg( "body_background", tempRect
.width(), tempRect
.height() ) );
885 //make sure that the top text items are not shown
886 if( m_items
->topRightText
->isVisible() )
887 m_items
->topRightText
->hide();
888 if( m_items
->topLeftText
->isVisible() )
889 m_items
->topLeftText
->hide();
890 if( !m_items
->bottomRightText
->isVisible() )
891 m_items
->bottomRightText
->show();
892 if( !m_items
->bottomLeftText
->isVisible() )
893 m_items
->bottomLeftText
->show();
895 //set selection marker if needed
896 if( option
->state
& QStyle::State_Selected
)
899 painter
->drawPixmap( 2, (int)trackRect
.top(), getCachedSvg( "selection_left", 40, trackRect
.height() ) );
900 painter
->drawPixmap( (int)trackRect
.width() - 42, (int)trackRect
.top(), getCachedSvg( "selection_right", 40, trackRect
.height() ) );
903 //set overlay if item is active
904 handleActiveOverlay( trackRect
, active
);
908 void Playlist::GraphicsItem::paintCollapsed()
911 // just make sure text items are hidden and then get the heck out of here...
912 if( m_items
->topRightText
->isVisible() )
913 m_items
->topRightText
->hide();
914 if( m_items
->topLeftText
->isVisible() )
915 m_items
->topLeftText
->hide();
916 if( m_items
->bottomRightText
->isVisible() )
917 m_items
->bottomRightText
->hide();
918 if( m_items
->bottomLeftText
->isVisible() )
919 m_items
->bottomLeftText
->hide();
922 QPixmap
Playlist::GraphicsItem::getCachedSvg( QString name
, int width
, int height
)
924 QString key
= QString("%1:%2x%3").arg( name
).arg( width
).arg( height
);
925 QPixmap
pixmap( width
, height
);
926 pixmap
.fill( Qt::transparent
);
928 if( !QPixmapCache::find(key
, pixmap
) )
930 QPainter
pt2( &pixmap
);
931 s_svgRenderer
->render( &pt2
, name
, QRectF( 0, 0, width
, height
) );
932 QPixmapCache::insert(key
, pixmap
);
938 void Playlist::GraphicsItem::handleActiveOverlay( QRectF rect
, bool active
)
942 if( !m_items
->foreground
)
945 debug() << "Creating active track overlay";
946 m_items
->foreground
= new QGraphicsPixmapItem( this );
947 m_items
->foreground
->setPos( 0.0, rect
.top() );
948 m_items
->foreground
->setZValue( 10.0 );
950 m_items
->foreground
->setPixmap( getCachedSvg( "active_overlay", rect
.width(), rect
.height() ) );
951 m_items
->foreground
->show();
955 if( !m_items
->foreground
->isVisible() )
956 m_items
->foreground
->show();
958 else if( m_items
->foreground
&& m_items
->foreground
->isVisible() )
959 m_items
->foreground
->hide();