/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. #include "albumitemdelegate.h"
  19. #include <QApplication>
  20. #include <QPainter>
  21. #include <QAbstractItemView>
  22. #include "artist.h"
  23. #include "query.h"
  24. #include "result.h"
  25. #include "utils/tomahawkutils.h"
  26. #include "utils/logger.h"
  27. #include "playlist/albumitem.h"
  28. #include "playlist/albumproxymodel.h"
  29. #include <QMouseEvent>
  30. #include <viewmanager.h>
  31. AlbumItemDelegate::AlbumItemDelegate( QAbstractItemView* parent, AlbumProxyModel* proxy )
  32. : QStyledItemDelegate( (QObject*)parent )
  33. , m_view( parent )
  34. , m_model( proxy )
  35. {
  36. m_defaultCover = QPixmap( RESPATH "images/no-album-art-placeholder.png" );
  37. }
  38. QSize
  39. AlbumItemDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
  40. {
  41. QSize size = QStyledItemDelegate::sizeHint( option, index );
  42. return size;
  43. }
  44. void
  45. AlbumItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
  46. {
  47. AlbumItem* item = m_model->sourceModel()->itemFromIndex( m_model->mapToSource( index ) );
  48. if ( !item )
  49. return;
  50. QStyleOptionViewItemV4 opt = option;
  51. initStyleOption( &opt, QModelIndex() );
  52. qApp->style()->drawControl( QStyle::CE_ItemViewItem, &opt, painter );
  53. painter->save();
  54. painter->setRenderHint( QPainter::Antialiasing );
  55. if ( !( option.state & QStyle::State_Selected ) )
  56. {
  57. QRect shadowRect = option.rect.adjusted( 5, 4, -5, -40 );
  58. painter->setPen( QColor( 90, 90, 90 ) );
  59. painter->drawRoundedRect( shadowRect, 0.5, 0.5 );
  60. QPen shadowPen( QColor( 30, 30, 30 ) );
  61. shadowPen.setWidth( 0.4 );
  62. painter->drawLine( shadowRect.bottomLeft() + QPoint( -1, 2 ), shadowRect.bottomRight() + QPoint( 1, 2 ) );
  63. shadowPen.setColor( QColor( 160, 160, 160 ) );
  64. painter->setPen( shadowPen );
  65. painter->drawLine( shadowRect.topLeft() + QPoint( -1, 2 ), shadowRect.bottomLeft() + QPoint( -1, 2 ) );
  66. painter->drawLine( shadowRect.topRight() + QPoint( 2, 2 ), shadowRect.bottomRight() + QPoint( 2, 2 ) );
  67. painter->drawLine( shadowRect.bottomLeft() + QPoint( 0, 3 ), shadowRect.bottomRight() + QPoint( 0, 3 ) );
  68. shadowPen.setColor( QColor( 180, 180, 180 ) );
  69. painter->setPen( shadowPen );
  70. painter->drawLine( shadowRect.topLeft() + QPoint( -2, 3 ), shadowRect.bottomLeft() + QPoint( -2, 1 ) );
  71. painter->drawLine( shadowRect.topRight() + QPoint( 3, 3 ), shadowRect.bottomRight() + QPoint( 3, 1 ) );
  72. painter->drawLine( shadowRect.bottomLeft() + QPoint( 0, 4 ), shadowRect.bottomRight() + QPoint( 0, 4 ) );
  73. }
  74. QPixmap cover;
  75. if ( !item->album().isNull() )
  76. {
  77. cover.loadFromData( item->album()->cover() );
  78. }
  79. else if ( !item->artist().isNull() )
  80. {
  81. cover.loadFromData( item->artist()->cover() );
  82. }
  83. if ( cover.isNull() )
  84. cover = m_defaultCover;
  85. QRect r = option.rect.adjusted( 6, 5, -6, -41 );
  86. if ( option.state & QStyle::State_Selected )
  87. {
  88. #if defined(Q_WS_MAC) || defined(Q_WS_WIN)
  89. painter->save();
  90. painter->setRenderHint( QPainter::Antialiasing );
  91. QPainterPath border;
  92. border.addRoundedRect( r.adjusted( -2, -2, 2, 2 ), 3, 3 );
  93. QPen borderPen( QColor( 86, 170, 243 ) );
  94. borderPen.setWidth( 5 );
  95. painter->setPen( borderPen );
  96. painter->drawPath( border );
  97. painter->restore();
  98. #else
  99. opt.palette.setColor( QPalette::Text, opt.palette.color( QPalette::HighlightedText ) );
  100. #endif
  101. }
  102. QPixmap scover;
  103. if ( m_cache.contains( cover.cacheKey() ) )
  104. {
  105. scover = m_cache.value( cover.cacheKey() );
  106. }
  107. else
  108. {
  109. scover = cover.scaled( r.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation );
  110. m_cache.insert( cover.cacheKey(), scover );
  111. }
  112. painter->drawPixmap( r, scover );
  113. painter->setPen( opt.palette.color( QPalette::Text ) );
  114. QTextOption to;
  115. to.setWrapMode( QTextOption::NoWrap );
  116. QString text;
  117. QFont font = opt.font;
  118. font.setPixelSize( 11 );
  119. QFont boldFont = font;
  120. boldFont.setBold( true );
  121. QRect textRect = option.rect.adjusted( 0, option.rect.height() - 32, 0, -2 );
  122. QString name;
  123. if ( !item->album().isNull() )
  124. name = item->album()->name();
  125. else if ( !item->artist().isNull() )
  126. name = item->artist()->name();
  127. painter->setFont( boldFont );
  128. bool oneLiner = false;
  129. if ( item->album().isNull() || item->album()->artist().isNull() )
  130. oneLiner = true;
  131. else
  132. oneLiner = ( textRect.height() / 2 < painter->fontMetrics().boundingRect( item->album()->name() ).height() ||
  133. textRect.height() / 2 < painter->fontMetrics().boundingRect( item->album()->artist()->name() ).height() );
  134. if ( oneLiner )
  135. {
  136. to.setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
  137. text = painter->fontMetrics().elidedText( name, Qt::ElideRight, textRect.width() - 3 );
  138. painter->drawText( textRect, text, to );
  139. }
  140. else
  141. {
  142. to.setAlignment( Qt::AlignHCenter | Qt::AlignTop );
  143. text = painter->fontMetrics().elidedText( item->album()->name(), Qt::ElideRight, textRect.width() - 3 );
  144. painter->drawText( textRect, text, to );
  145. // If the user is hovering over an artist rect, draw a background so she knows it's clickable
  146. QRect r = textRect;
  147. r.setTop( r.bottom() - painter->fontMetrics().height() );
  148. r.adjust( 4, 0, -4, -1 );
  149. if ( m_hoveringOver == index )
  150. {
  151. TomahawkUtils::drawQueryBackground( painter, opt.palette, r, 1.1 );
  152. painter->setPen( opt.palette.color( QPalette::HighlightedText ) );
  153. }
  154. else
  155. {
  156. if ( !( option.state & QStyle::State_Selected ) )
  157. #ifdef Q_WS_MAC
  158. painter->setPen( opt.palette.color( QPalette::Dark ).darker( 200 ) );
  159. #else
  160. painter->setPen( opt.palette.color( QPalette::Dark ) );
  161. #endif
  162. }
  163. to.setAlignment( Qt::AlignHCenter | Qt::AlignBottom );
  164. text = painter->fontMetrics().elidedText( item->album()->artist()->name(), Qt::ElideRight, textRect.width() - 10 );
  165. painter->drawText( textRect.adjusted( 5, -1, -5, -1 ), text, to );
  166. // Calculate rect of artist on-hover button click area
  167. m_artistNameRects[ index ] = r;
  168. }
  169. painter->restore();
  170. }
  171. bool
  172. AlbumItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index )
  173. {
  174. Q_UNUSED( model );
  175. Q_UNUSED( option );
  176. if ( event->type() != QEvent::MouseButtonRelease &&
  177. event->type() != QEvent::MouseMove &&
  178. event->type() != QEvent::MouseButtonPress &&
  179. event->type() != QEvent::Leave )
  180. return false;
  181. if ( m_artistNameRects.contains( index ) )
  182. {
  183. QMouseEvent* ev = static_cast< QMouseEvent* >( event );
  184. QRect artistNameRect = m_artistNameRects[ index ];
  185. if ( artistNameRect.contains( ev->pos() ) )
  186. {
  187. if ( event->type() == QEvent::MouseMove )
  188. {
  189. if ( m_hoveringOver != index )
  190. {
  191. QModelIndex old = m_hoveringOver;
  192. m_hoveringOver = index;
  193. emit updateIndex( old );
  194. emit updateIndex( index );
  195. }
  196. event->accept();
  197. return true;
  198. }
  199. else if ( event->type() == QEvent::MouseButtonRelease )
  200. {
  201. AlbumItem* item = m_model->sourceModel()->itemFromIndex( m_model->mapToSource( index ) );
  202. if ( !item || item->album().isNull() || item->album()->artist().isNull() )
  203. return false;
  204. ViewManager::instance()->show( item->album()->artist() );
  205. event->accept();
  206. return true;
  207. }
  208. else if ( event->type() == QEvent::MouseButtonPress )
  209. {
  210. // Stop the whole album from having a down click action as we just want the artist name to be clicked
  211. event->accept();
  212. return true;
  213. }
  214. }
  215. }
  216. whitespaceMouseEvent();
  217. return false;
  218. }
  219. void
  220. AlbumItemDelegate::whitespaceMouseEvent()
  221. {
  222. if ( m_hoveringOver.isValid() )
  223. {
  224. QModelIndex old = m_hoveringOver;
  225. m_hoveringOver = QPersistentModelIndex();
  226. emit updateIndex( old );
  227. }
  228. }