Commit 9cd740c4eccb16f184fe13931802d3948ab4fe85

The incredible playlist delegate
  
11#include "playlistitemdelegate.h"
22#include "model/track.h"
3#include "model/album.h"
4#include "model/artist.h"
35#include "playlistmodel.h"
46
7const int PlaylistItemDelegate::PADDING = 10;
8int PlaylistItemDelegate::ITEM_HEIGHT = 0;
9
510PlaylistItemDelegate::PlaylistItemDelegate(QObject *parent) :
611 QStyledItemDelegate(parent) {
712
813}
914
15QSize PlaylistItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const {
16
17 // determine item height based on font metrics
18 if (ITEM_HEIGHT == 0) {
19 ITEM_HEIGHT = option.fontMetrics.height() * 2;
20 }
21
22 QModelIndex previousIndex = index.sibling(index.row()-1, index.column());
23 if (previousIndex.isValid()) {
24 const TrackPointer previousTrackPointer = previousIndex.data(Playlist::DataObjectRole).value<TrackPointer>();
25 Track *previousTrack = previousTrackPointer.data();
26 if (previousTrack) {
27 const TrackPointer trackPointer = index.data(Playlist::DataObjectRole).value<TrackPointer>();
28 Track *track = trackPointer.data();
29 if (previousTrack->getAlbum() != track->getAlbum()) {
30 return QSize(ITEM_HEIGHT*2, ITEM_HEIGHT*2);
31 }
32 }
33 } else {
34 return QSize(ITEM_HEIGHT*2, ITEM_HEIGHT*2);
35 }
36
37 return QSize(ITEM_HEIGHT, ITEM_HEIGHT);
38}
39
1040void PlaylistItemDelegate::paint( QPainter* painter,
1141 const QStyleOptionViewItem& option,
1242 const QModelIndex& index ) const {
1343
14 QApplication::style()->drawPrimitive( QStyle::PE_PanelItemViewItem, &option, painter );
1544 paintTrack(painter, option, index);
1645
1746}
5353 const TrackPointer trackPointer = index.data(Playlist::DataObjectRole).value<TrackPointer>();
5454 Track *track = trackPointer.data();
5555
56 // const PlaylistModel* playlistModel = dynamic_cast<const PlaylistModel*>(index.model());
57
58 const bool isActive = index.data(Playlist::ActiveItemRole).toBool();
59 // const bool isHovered = index.data(Playlist::HoveredItemRole).toBool();
60 const bool isSelected = option.state & QStyle::State_Selected;
61
62 if (isSelected)
63 QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter);
64
65 painter->save();
66
67 painter->translate(option.rect.topLeft());
68 QRect line(0, 0, option.rect.width(), option.rect.height());
69
70 if (line.height() > ITEM_HEIGHT) {
71 // qDebug() << "header at index" << index.row();
72 line.setHeight(ITEM_HEIGHT);
73 paintAlbumHeader(painter, option, line, track);
74
75 // now modify our rect and painter
76 // to make them similar to "headerless" items
77 line.moveBottom(ITEM_HEIGHT);
78 painter->translate(0, ITEM_HEIGHT);
79 }
80
81 if (isActive) {
82 if (!isSelected) paintActiveOverlay(painter, option, line);
83 QFont boldFont = painter->font();
84 boldFont.setBold(true);
85 painter->setFont(boldFont);
86 }
87
88 paintTrackNumber(painter, option, line, track);
89 paintTrackTitle(painter, option, line, track);
90 paintTrackLength(painter, option, line, track);
91
92 // separator
93 painter->setPen(option.palette.color(QPalette::Midlight));
94 painter->drawLine(0, line.height()-1, line.width(), line.height()-1);
95
96 painter->restore();
97}
98
99void PlaylistItemDelegate::paintAlbumHeader(
100 QPainter* painter, const QStyleOptionViewItem& option, QRect line, Track* track) const {
101
102 QString headerTitle;
103 Album *album = track->getAlbum();
104 if (album) headerTitle = album->getTitle();
105 Artist *artist = track->getArtist();
106 if (artist) headerTitle += " - " + artist->getName();
107
108 painter->save();
109
110 // cover background
111 /*
112 QImage p = album->getPhoto();
113 if (!p.isNull()) {
114 painter->drawTiledPixmap(line, QPixmap::fromImage(p));
115 QLinearGradient linearGrad(0, 0, 0, line.height());
116 linearGrad.setColorAt(0, QColor(0,0,0, 96));
117 linearGrad.setColorAt(1, QColor(0,0,0, 64));
118 painter->fillRect(line, QBrush(linearGrad));
119 } else {
120 QLinearGradient linearGrad(0, 0, 0, line.height());
121 linearGrad.setColorAt(0, option.palette.color(QPalette::Mid));
122 linearGrad.setColorAt(1, option.palette.midlight().color());
123 painter->fillRect(line, QBrush(linearGrad));
124 }*/
125
126 QLinearGradient linearGrad(0, 0, 0, line.height());
127 linearGrad.setColorAt(0, option.palette.color(QPalette::Mid));
128 linearGrad.setColorAt(1, option.palette.midlight().color());
129 painter->fillRect(line, QBrush(linearGrad));
130
131 // borders
132 painter->setPen(option.palette.color(QPalette::Light));
133 painter->drawLine(0, 0, line.width(), 0);
134 painter->setPen(option.palette.color(QPalette::Mid));
135 painter->drawLine(0, line.height()-1, line.width(), line.height()-1);
136
137 // font
138 QFont boldFont = painter->font();
139 boldFont.setBold(true);
140 painter->setFont(boldFont);
141
142 // text size
143 QSize trackStringSize(QFontMetrics(painter->font()).size(Qt::TextSingleLine, headerTitle));
144 QPoint textLoc(PADDING*6, 0);
145 QRect trackTextBox(textLoc.x(), textLoc.y(), trackStringSize.width(), line.height());
146
147 // text shadow
148 painter->setOpacity(.5);
149 painter->setPen(Qt::black);
150 painter->drawText(trackTextBox.translated(0, -1), Qt::AlignLeft | Qt::AlignVCenter, headerTitle);
151
152 // text
153 painter->setOpacity(1);
154 painter->setPen(option.palette.color(QPalette::Light));
155 painter->drawText(trackTextBox, Qt::AlignLeft | Qt::AlignVCenter, headerTitle);
156
157 // album length
158 if (album) {
159 // TODO this is the album duration, but not necessarily what we have in the playlist
160 int totalLength = Track::getTotalLength(album->getTracks());
161 QString albumLength;
162 if (totalLength > 3600)
163 albumLength = QTime().addSecs(totalLength).toString("h:mm:ss");
164 else
165 albumLength = QTime().addSecs(totalLength).toString("m:ss");
166 QFont normalFont = painter->font();
167 normalFont.setBold(false);
168 // normalFont.setPointSize(boldFont.pointSize()*.9);
169 painter->setFont(normalFont);
170 painter->drawText(line.translated(-PADDING, 0), Qt::AlignRight | Qt::AlignVCenter, albumLength);
171 }
172
173 // TODO album year
174
175 painter->restore();
176}
177
178void PlaylistItemDelegate::paintTrackNumber(
179 QPainter* painter, const QStyleOptionViewItem& option, QRect line, Track* track) const {
180
181 const int trackNumber = track->getNumber();
182 if (trackNumber < 1) return;
183
184 painter->save();
185
186 // track number
187 QFont boldFont = painter->font();
188 boldFont.setBold(true);
189 boldFont.setPointSize(boldFont.pointSize()*.9);
190 painter->setFont(boldFont);
191 QString trackString = QString("%1").arg(trackNumber, 2, 10, QChar('0'));
192 QSize trackStringSize(QFontMetrics(painter->font()).size( Qt::TextSingleLine, trackString));
193 QPoint textLoc(PADDING*2, 0);
194 QRect trackTextBox(textLoc.x(), textLoc.y(), trackStringSize.width(), line.height());
195
196 // rounded rect
197 QRect trackRoundedRect = trackTextBox;
198 trackRoundedRect.setY((line.height() - trackStringSize.height()) / 2);
199 trackRoundedRect.setHeight(trackStringSize.height());
200 trackRoundedRect.adjust(-PADDING/2, -PADDING/3, PADDING/2, PADDING/3);
201 painter->setOpacity(.5);
202 painter->setRenderHints(QPainter::Antialiasing, true);
203 painter->setBrush(option.palette.window());
204 painter->setPen(option.palette.WindowText);
205
206 painter->drawRoundedRect(trackRoundedRect, PADDING/2, PADDING/2, Qt::AbsoluteSize);
207 painter->drawText(trackTextBox, Qt::AlignCenter, trackString);
208
209 painter->restore();
210
211}
212
213void PlaylistItemDelegate::paintTrackTitle(
214 QPainter* painter, const QStyleOptionViewItem& option, QRect line, Track* track) const {
215
216 const QString trackTitle = track->getTitle();
217 QSize trackStringSize(QFontMetrics(painter->font()).size(Qt::TextSingleLine, trackTitle));
218 QPoint textLoc(PADDING*6, 0);
219 QRect trackTextBox(textLoc.x(), textLoc.y(), trackStringSize.width(), line.height());
220
221 painter->drawText(trackTextBox, Qt::AlignLeft | Qt::AlignVCenter, trackTitle);
222
223}
224
225void PlaylistItemDelegate::paintTrackLength(
226 QPainter* painter, const QStyleOptionViewItem& option, QRect line, Track* track) const {
227
228 QString trackLength;
229 if (track->getLength() > 3600)
230 trackLength = QTime().addSecs(track->getLength()).toString("h:mm:ss");
231 else if (track->getLength() > 0)
232 trackLength = QTime().addSecs(track->getLength()).toString("m:ss");
233
234 // QSize trackStringSize(QFontMetrics(painter->font()).size(Qt::TextSingleLine, trackLength));
235 QPoint textLoc(PADDING*10, 0);
236 QRect trackTextBox(textLoc.x(), textLoc.y(), line.width() - textLoc.x() - PADDING, line.height());
237
238 painter->drawText(trackTextBox, Qt::AlignRight | Qt::AlignVCenter, trackLength);
239
240}
241
242void PlaylistItemDelegate::paintActiveOverlay(
243 QPainter *painter, const QStyleOptionViewItem& option, QRect line) const {
244
245 QColor highlightColor = option.palette.color(QPalette::Highlight);
246 QColor backgroundColor = option.palette.color(QPalette::Base);
247 const float animation = 0.25;
248 const int gradientRange = 16;
249
250 QColor color2 = QColor::fromHsv(
251 highlightColor.hue(),
252 (int) (backgroundColor.saturation() * (1.0f - animation) + highlightColor.saturation() * animation),
253 (int) (backgroundColor.value() * (1.0f - animation) + highlightColor.value() * animation)
254 );
255 QColor color1 = QColor::fromHsv(
256 color2.hue(),
257 qMax(color2.saturation() - gradientRange, 0),
258 qMin(color2.value() + gradientRange, 255)
259 );
260
261 painter->save();
262 painter->setPen(Qt::NoPen);
263 QLinearGradient linearGradient(0, 0, 0, line.height());
264 linearGradient.setColorAt(0.0, color1);
265 linearGradient.setColorAt(1.0, color2);
266 painter->setBrush(linearGradient);
267 painter->drawRect(line);
268 painter->restore();
56269}
  
33
44#include <QtGui>
55
6class Track;
7
68class PlaylistItemDelegate : public QStyledItemDelegate {
79
810 Q_OBJECT
911
1012public:
1113 PlaylistItemDelegate(QObject *parent = 0);
12 // QSize sizeHint( const QStyleOptionViewItem&, const QModelIndex&) const;
14 QSize sizeHint( const QStyleOptionViewItem&, const QModelIndex&) const;
1315 void paint( QPainter*, const QStyleOptionViewItem&, const QModelIndex&) const;
1416
1517private:
16 void paintTrack( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
18 void paintTrack(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
19 void paintAlbumHeader(QPainter* painter, const QStyleOptionViewItem& option, QRect line, Track* track) const;
20 void paintTrackNumber(QPainter* painter, const QStyleOptionViewItem& option, QRect line, Track* track) const;
21 void paintTrackTitle(QPainter* painter, const QStyleOptionViewItem& option, QRect line, Track* track) const;
22 void paintTrackLength(QPainter* painter, const QStyleOptionViewItem& option, QRect line, Track* track) const;
23 void paintActiveOverlay(QPainter *painter, const QStyleOptionViewItem& option, QRect line) const;
1724
1825 static const int PADDING;
26 static int ITEM_HEIGHT;
27
28
1929
2030};
2131