1 #include "PrettyItemDelegate.h"
2 #include "../ListModel.h"
4 #include <QFontMetricsF>
7 const qreal PrettyItemDelegate::THUMB_HEIGHT = 90.0;
8 const qreal PrettyItemDelegate::THUMB_WIDTH = 120.0;
9 const qreal PrettyItemDelegate::PADDING = 10.0;
11 PrettyItemDelegate::PrettyItemDelegate( QObject* parent ) : QStyledItemDelegate( parent ) {
13 boldFont.setBold(true);
14 smallerFont.setPointSize(smallerFont.pointSize()*.85);
15 smallerBoldFont.setBold(true);
16 smallerBoldFont.setPointSize(smallerBoldFont.pointSize()*.85);
17 QFontInfo fontInfo(smallerFont);
18 if (fontInfo.pixelSize() < 10) {
19 smallerFont.setPixelSize(10);
20 smallerBoldFont.setPixelSize(10);
25 void PrettyItemDelegate::createPlayIcon() {
26 playIcon = QPixmap(THUMB_WIDTH, THUMB_HEIGHT);
27 playIcon.fill(Qt::transparent);
28 QPainter painter(&playIcon);
30 polygon << QPoint(PADDING*4, PADDING*2)
31 << QPoint(THUMB_WIDTH-PADDING*4, THUMB_HEIGHT/2)
32 << QPoint(PADDING*4, THUMB_HEIGHT-PADDING*2);
33 painter.setRenderHints(QPainter::Antialiasing, true);
34 painter.setBrush(Qt::white);
36 pen.setColor(Qt::white);
37 pen.setWidth(PADDING);
38 pen.setJoinStyle(Qt::RoundJoin);
39 pen.setCapStyle(Qt::RoundCap);
41 painter.drawPolygon(polygon);
44 PrettyItemDelegate::~PrettyItemDelegate() { }
46 QSize PrettyItemDelegate::sizeHint( const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/ ) const {
47 return QSize( 256, THUMB_HEIGHT+1.0);
50 void PrettyItemDelegate::paint( QPainter* painter,
51 const QStyleOptionViewItem& option, const QModelIndex& index ) const {
53 int itemType = index.data(ItemTypeRole).toInt();
54 if (itemType == ItemTypeVideo) {
55 QApplication::style()->drawPrimitive( QStyle::PE_PanelItemViewItem, &option, painter );
56 paintBody( painter, option, index );
58 QStyledItemDelegate::paint( painter, option, index );
62 void PrettyItemDelegate::paintBody( QPainter* painter,
63 const QStyleOptionViewItem& option,
64 const QModelIndex& index ) const {
67 painter->translate( option.rect.topLeft() );
70 const QRectF line(0, 0, option.rect.width(), option.rect.height());
71 painter->setClipRect(line);
73 const bool isActive = index.data( ActiveTrackRole ).toBool();
74 const bool isSelected = option.state & QStyle::State_Selected;
76 // draw the "current track" highlight underneath the text
77 if (isActive && !isSelected) {
78 paintActiveOverlay(painter, line.x(), line.y(), line.width(), line.height());
81 // get the video metadata
82 const VideoPointer videoPointer = index.data( VideoRole ).value<VideoPointer>();
83 const Video *video = videoPointer.data();
86 if (!video->thumbnail().isNull()) {
87 painter->drawImage(QRect(0, 0, THUMB_WIDTH, THUMB_HEIGHT), video->thumbnail());
89 // play icon overlayed on the thumb
91 paintPlayIcon(painter);
95 int duration = video->duration();
96 if ( duration > 3600 )
97 timeString = QTime().addSecs(duration).toString("h:mm:ss");
99 timeString = QTime().addSecs(duration).toString("m:ss");
100 drawTime(painter, timeString, line);
104 if (isActive) painter->setFont(boldFont);
105 const QFontMetricsF fm(painter->font());
106 const QFontMetricsF boldMetrics(boldFont);
110 painter->setPen(QPen(option.palette.brush(QPalette::HighlightedText), 0));
112 painter->setPen(QPen(option.palette.brush(QPalette::Text), 0));
115 QString videoTitle = video->title();
116 QRectF textBox = line.adjusted(PADDING+THUMB_WIDTH, PADDING, -2 * PADDING, -PADDING);
117 textBox = painter->boundingRect( textBox, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, videoTitle);
118 painter->drawText(textBox, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, videoTitle);
120 painter->setFont(smallerFont);
123 QString publishedString = video->published().date().toString(Qt::DefaultLocaleShortDate);
124 QSizeF publishedStringSize(QFontMetrics(painter->font()).size( Qt::TextSingleLine, publishedString ) );
125 QPointF textLoc(PADDING+THUMB_WIDTH, PADDING*2 + textBox.height());
126 QRectF publishedTextBox( textLoc , publishedStringSize);
127 painter->drawText(publishedTextBox, Qt::AlignLeft | Qt::AlignTop, publishedString);
131 painter->setFont(smallerBoldFont);
132 if (!isSelected && !isActive)
133 painter->setPen(QPen(option.palette.brush(QPalette::Mid), 0));
134 QString authorString = video->author();
135 QSizeF authorStringSize(QFontMetrics(painter->font()).size( Qt::TextSingleLine, authorString ) );
136 textLoc.setX(textLoc.x() + publishedStringSize.width() + PADDING);
137 QRectF authorTextBox( textLoc , authorStringSize);
138 painter->drawText(authorTextBox, Qt::AlignLeft | Qt::AlignTop, authorString);
142 if (video->viewCount() >= 0) {
145 QString viewCountString = tr("%1 views").arg(locale.toString(video->viewCount()));
146 QSizeF viewCountStringSize(QFontMetrics(painter->font()).size( Qt::TextSingleLine, viewCountString ) );
147 textLoc.setX(textLoc.x() + authorStringSize.width() + PADDING);
148 QRectF viewCountTextBox( textLoc , viewCountStringSize);
149 painter->drawText(viewCountTextBox, Qt::AlignLeft | Qt::AlignBottom, viewCountString);
154 QLinearGradient myGradient;
157 QPointF baseline(authorTextBox.x(), authorTextBox.y() + authorTextBox.height());
159 myPath.addText(baseline, boldFont, authorString);
160 painter->setBrush(palette.color(QPalette::WindowText));
161 painter->setPen(palette.color(QPalette::Dark));
162 painter->setRenderHints (QPainter::Antialiasing, true);
163 painter->drawPath(myPath);
167 painter->setPen(option.palette.color(QPalette::Midlight));
168 painter->drawLine(THUMB_WIDTH, THUMB_HEIGHT, line.width(), THUMB_HEIGHT);
169 if (!video->thumbnail().isNull())
170 painter->setPen(Qt::black);
171 painter->drawLine(0, THUMB_HEIGHT, THUMB_WIDTH-1, THUMB_HEIGHT);
177 QPointF PrettyItemDelegate::centerImage( const QPixmap& pixmap, const QRectF& rect ) const {
178 qreal pixmapRatio = ( qreal )pixmap.width() / ( qreal )pixmap.height();
183 if ( pixmapRatio >= 1 )
184 moveByY = ( rect.height() - ( rect.width() / pixmapRatio ) ) / 2.0;
186 moveByX = ( rect.width() - ( rect.height() * pixmapRatio ) ) / 2.0;
188 return QPointF( moveByX, moveByY );
191 void PrettyItemDelegate::paintActiveOverlay( QPainter *painter, qreal x, qreal y, qreal w, qreal h ) const {
194 QColor highlightColor = palette.color(QPalette::Highlight);
195 QColor backgroundColor = palette.color(QPalette::Base);
196 const float animation = 0.25;
197 const int gradientRange = 16;
199 QColor color2 = QColor::fromHsv(
200 highlightColor.hue(),
201 (int) (backgroundColor.saturation() * (1.0f - animation) + highlightColor.saturation() * animation),
202 (int) (backgroundColor.value() * (1.0f - animation) + highlightColor.value() * animation)
204 QColor color1 = QColor::fromHsv(
206 qMax(color2.saturation() - gradientRange, 0),
207 qMin(color2.value() + gradientRange, 255)
209 QRect rect((int) x, (int) y, (int) w, (int) h);
211 painter->setPen(Qt::NoPen);
212 QLinearGradient linearGradient(0, 0, 0, rect.height());
213 linearGradient.setColorAt(0.0, color1);
214 linearGradient.setColorAt(1.0, color2);
215 painter->setBrush(linearGradient);
216 painter->drawRect(rect);
220 void PrettyItemDelegate::paintPlayIcon(QPainter *painter) const {
222 painter->setOpacity(.5);
223 painter->drawPixmap(playIcon.rect(), playIcon);
227 void PrettyItemDelegate::drawTime(QPainter *painter, QString time, QRectF line) const {
228 static const int timePadding = 4;
229 QRectF textBox = painter->boundingRect(line, Qt::AlignLeft | Qt::AlignTop, time);
231 textBox.adjust(0, 0, timePadding, 0);
232 // move to bottom right corner of the thumb
233 textBox.translate(THUMB_WIDTH - textBox.width(), THUMB_HEIGHT - textBox.height());
236 painter->setPen(Qt::NoPen);
237 painter->setBrush(Qt::black);
238 painter->setOpacity(.5);
239 painter->drawRect(textBox);
243 painter->setPen(Qt::white);
244 painter->drawText(textBox, Qt::AlignCenter, time);