Commit 9cd740c4eccb16f184fe13931802d3948ab4fe85
- Diff rendering mode:
- inline
- side by side
src/playlistitemdelegate.cpp
(243 / 1)
|   | |||
| 1 | 1 | #include "playlistitemdelegate.h" | |
| 2 | 2 | #include "model/track.h" | |
| 3 | #include "model/album.h" | ||
| 4 | #include "model/artist.h" | ||
| 3 | 5 | #include "playlistmodel.h" | |
| 4 | 6 | ||
| 7 | const int PlaylistItemDelegate::PADDING = 10; | ||
| 8 | int PlaylistItemDelegate::ITEM_HEIGHT = 0; | ||
| 9 | |||
| 5 | 10 | PlaylistItemDelegate::PlaylistItemDelegate(QObject *parent) : | |
| 6 | 11 | QStyledItemDelegate(parent) { | |
| 7 | 12 | ||
| 8 | 13 | } | |
| 9 | 14 | ||
| 15 | QSize 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 | |||
| 10 | 40 | void PlaylistItemDelegate::paint( QPainter* painter, | |
| 11 | 41 | const QStyleOptionViewItem& option, | |
| 12 | 42 | const QModelIndex& index ) const { | |
| 13 | 43 | ||
| 14 | QApplication::style()->drawPrimitive( QStyle::PE_PanelItemViewItem, &option, painter ); | ||
| 15 | 44 | paintTrack(painter, option, index); | |
| 16 | 45 | ||
| 17 | 46 | } | |
| … | … | ||
| 53 | 53 | const TrackPointer trackPointer = index.data(Playlist::DataObjectRole).value<TrackPointer>(); | |
| 54 | 54 | Track *track = trackPointer.data(); | |
| 55 | 55 | ||
| 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 | |||
| 99 | void 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 | |||
| 178 | void 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 | |||
| 213 | void 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 | |||
| 225 | void 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 | |||
| 242 | void 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(); | ||
| 56 | 269 | } |
src/playlistitemdelegate.h
(12 / 2)
|   | |||
| 3 | 3 | ||
| 4 | 4 | #include <QtGui> | |
| 5 | 5 | ||
| 6 | class Track; | ||
| 7 | |||
| 6 | 8 | class PlaylistItemDelegate : public QStyledItemDelegate { | |
| 7 | 9 | ||
| 8 | 10 | Q_OBJECT | |
| 9 | 11 | ||
| 10 | 12 | public: | |
| 11 | 13 | PlaylistItemDelegate(QObject *parent = 0); | |
| 12 | // QSize sizeHint( const QStyleOptionViewItem&, const QModelIndex&) const; | ||
| 14 | QSize sizeHint( const QStyleOptionViewItem&, const QModelIndex&) const; | ||
| 13 | 15 | void paint( QPainter*, const QStyleOptionViewItem&, const QModelIndex&) const; | |
| 14 | 16 | ||
| 15 | 17 | private: | |
| 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; | ||
| 17 | 24 | ||
| 18 | 25 | static const int PADDING; | |
| 26 | static int ITEM_HEIGHT; | ||
| 27 | |||
| 28 | |||
| 19 | 29 | ||
| 20 | 30 | }; | |
| 21 | 31 |

