~ubuntu-branches/ubuntu/saucy/minitube/saucy

« back to all changes in this revision

Viewing changes to src/playlist/PrettyItemDelegate.cpp

  • Committer: Package Import Robot
  • Author(s): Jakob Haufe
  • Date: 2013-05-23 13:54:01 UTC
  • mfrom: (1.1.15 sid)
  • Revision ID: package-import@ubuntu.com-20130523135401-wsbh1xtf71nkfvkt
Tags: 2.0-1
* New upstream version
* Switch from hardening-wrapper to buildflags.mk
* Refresh patches:
  - Drop gcc-4.7.patch, fixed upstream
  - Rebuild assure-quit-keybinding
  - Rebuild disable-update-check
* Update Standards-Version to 3.9.4
  - Add Vcs-* control fields
  - No further changes needed

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include "PrettyItemDelegate.h"
2
 
#include "../ListModel.h"
3
 
#include "../fontutils.h"
4
 
#include "../downloaditem.h"
5
 
#include "../iconloader/qticonloader.h"
6
 
#include "../videodefinition.h"
7
 
 
8
 
#include <QFontMetricsF>
9
 
#include <QPainter>
10
 
#include <QHash>
11
 
 
12
 
const qreal PrettyItemDelegate::THUMB_HEIGHT = 90.0;
13
 
const qreal PrettyItemDelegate::THUMB_WIDTH = 120.0;
14
 
const qreal PrettyItemDelegate::PADDING = 10.0;
15
 
 
16
 
QRect lastAuthorRect;
17
 
QHash<int, QRect> authorRects;
18
 
 
19
 
PrettyItemDelegate::PrettyItemDelegate(QObject* parent, bool downloadInfo)
20
 
    : QStyledItemDelegate(parent),
21
 
    downloadInfo(downloadInfo) {
22
 
    boldFont.setBold(true);
23
 
    smallerBoldFont = FontUtils::smallBold();
24
 
    smallerFont = FontUtils::small();
25
 
 
26
 
    if (downloadInfo) {
27
 
        progressBar = new QProgressBar(qApp->activeWindow());
28
 
        QPalette palette = progressBar->palette();
29
 
        palette.setColor(QPalette::Window, Qt::transparent);
30
 
        progressBar->setPalette(palette);
31
 
        progressBar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
32
 
        progressBar->hide();
33
 
    } else createPlayIcon();
34
 
}
35
 
 
36
 
void PrettyItemDelegate::createPlayIcon() {
37
 
    playIcon = QPixmap(THUMB_WIDTH, THUMB_HEIGHT);
38
 
    playIcon.fill(Qt::transparent);
39
 
    QPainter painter(&playIcon);
40
 
    QPolygon polygon;
41
 
    polygon << QPoint(PADDING*4, PADDING*2)
42
 
            << QPoint(THUMB_WIDTH-PADDING*4, THUMB_HEIGHT/2)
43
 
            << QPoint(PADDING*4, THUMB_HEIGHT-PADDING*2);
44
 
    painter.setRenderHints(QPainter::Antialiasing, true);
45
 
    painter.setBrush(Qt::white);
46
 
    QPen pen;
47
 
    pen.setColor(Qt::white);
48
 
    pen.setWidth(PADDING);
49
 
    pen.setJoinStyle(Qt::RoundJoin);
50
 
    pen.setCapStyle(Qt::RoundCap);
51
 
    painter.setPen(pen);
52
 
    painter.drawPolygon(polygon);
53
 
}
54
 
 
55
 
PrettyItemDelegate::~PrettyItemDelegate() { }
56
 
 
57
 
QSize PrettyItemDelegate::sizeHint( const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/ ) const {
58
 
    return QSize( 256, THUMB_HEIGHT+1.0);
59
 
}
60
 
 
61
 
void PrettyItemDelegate::paint( QPainter* painter,
62
 
                                const QStyleOptionViewItem& option, const QModelIndex& index ) const {
63
 
 
64
 
    int itemType = index.data(ItemTypeRole).toInt();
65
 
    if (itemType == ItemTypeVideo) {
66
 
        QStyleOptionViewItemV4 opt = QStyleOptionViewItemV4(option);
67
 
        initStyleOption(&opt, index);
68
 
        opt.text = "";
69
 
        opt.widget->style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget);
70
 
        paintBody(painter, opt, index);
71
 
    } else
72
 
        QStyledItemDelegate::paint( painter, option, index );
73
 
 
74
 
}
75
 
 
76
 
void PrettyItemDelegate::paintBody( QPainter* painter,
77
 
                                    const QStyleOptionViewItem& option,
78
 
                                    const QModelIndex& index ) const {
79
 
 
80
 
    painter->save();
81
 
    painter->translate( option.rect.topLeft() );
82
 
 
83
 
 
84
 
    QRectF line(0, 0, option.rect.width(), option.rect.height());
85
 
    if (downloadInfo) line.setWidth(line.width() / 2);
86
 
    painter->setClipRect(line);
87
 
 
88
 
    const bool isActive = index.data( ActiveTrackRole ).toBool();
89
 
    const bool isSelected = option.state & QStyle::State_Selected;
90
 
 
91
 
    // draw the "current track" highlight underneath the text
92
 
    if (isActive && !isSelected) {
93
 
        paintActiveOverlay(painter, line.x(), line.y(), line.width(), line.height());
94
 
    }
95
 
 
96
 
    // get the video metadata
97
 
    const VideoPointer videoPointer = index.data( VideoRole ).value<VideoPointer>();
98
 
    const Video *video = videoPointer.data();
99
 
 
100
 
    // thumb
101
 
    if (!video->thumbnail().isNull()) {
102
 
        painter->drawImage(QRect(0, 0, THUMB_WIDTH, THUMB_HEIGHT), video->thumbnail());
103
 
 
104
 
        // play icon overlayed on the thumb
105
 
        if (isActive)
106
 
            paintPlayIcon(painter);
107
 
 
108
 
        // time
109
 
        QString timeString;
110
 
        int duration = video->duration();
111
 
        if ( duration > 3600 )
112
 
            timeString = QTime().addSecs(duration).toString("h:mm:ss");
113
 
        else
114
 
            timeString = QTime().addSecs(duration).toString("m:ss");
115
 
        drawTime(painter, timeString, line);
116
 
 
117
 
    }
118
 
 
119
 
    if (isActive) painter->setFont(boldFont);
120
 
 
121
 
    // text color
122
 
    if (isSelected)
123
 
        painter->setPen(QPen(option.palette.brush(QPalette::HighlightedText), 0));
124
 
    else
125
 
        painter->setPen(QPen(option.palette.brush(QPalette::Text), 0));
126
 
 
127
 
    // title
128
 
    QString videoTitle = video->title();
129
 
    QRectF textBox = line.adjusted(PADDING+THUMB_WIDTH, PADDING, -2 * PADDING, -PADDING);
130
 
    textBox = painter->boundingRect( textBox, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, videoTitle);
131
 
    painter->drawText(textBox, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, videoTitle);
132
 
 
133
 
    painter->setFont(smallerFont);
134
 
 
135
 
    // published date
136
 
    QString publishedString = video->published().date().toString(Qt::DefaultLocaleShortDate);
137
 
    QSizeF stringSize(QFontMetrics(painter->font()).size( Qt::TextSingleLine, publishedString ) );
138
 
    QPointF textLoc(PADDING+THUMB_WIDTH, PADDING*2 + textBox.height());
139
 
    QRectF publishedTextBox(textLoc , stringSize);
140
 
    painter->drawText(publishedTextBox, Qt::AlignLeft | Qt::AlignTop, publishedString);
141
 
 
142
 
    // author
143
 
    bool authorHovered = false;
144
 
    bool authorPressed = false;
145
 
    const bool isHovered = index.data(HoveredItemRole).toBool();
146
 
    if (isHovered) {
147
 
        authorHovered = index.data(AuthorHoveredRole).toBool();
148
 
        authorPressed = index.data(AuthorPressedRole).toBool();
149
 
    }
150
 
 
151
 
    painter->save();
152
 
    painter->setFont(smallerBoldFont);
153
 
    if (!isSelected) {
154
 
        if (authorHovered)
155
 
            painter->setPen(QPen(option.palette.brush(QPalette::Highlight), 0));
156
 
        else
157
 
            painter->setPen(QPen(option.palette.brush(QPalette::Mid), 0));
158
 
    }
159
 
    QString authorString = video->author();
160
 
    textLoc.setX(textLoc.x() + stringSize.width() + PADDING);
161
 
    stringSize = QSizeF(QFontMetrics(painter->font()).size( Qt::TextSingleLine, authorString ) );
162
 
    QRectF authorTextBox(textLoc , stringSize);
163
 
    authorRects.insert(index.row(), authorTextBox.toRect());
164
 
    painter->drawText(authorTextBox, Qt::AlignLeft | Qt::AlignTop, authorString);
165
 
    painter->restore();
166
 
 
167
 
    // view count
168
 
    if (video->viewCount() >= 0) {
169
 
        painter->save();
170
 
        QLocale locale;
171
 
        QString viewCountString = tr("%1 views").arg(locale.toString(video->viewCount()));
172
 
        textLoc.setX(textLoc.x() + stringSize.width() + PADDING);
173
 
        stringSize = QSizeF(QFontMetrics(painter->font()).size( Qt::TextSingleLine, viewCountString ) );
174
 
        QRectF viewCountTextBox(textLoc , stringSize);
175
 
        painter->drawText(viewCountTextBox, Qt::AlignLeft | Qt::AlignBottom, viewCountString);
176
 
        painter->restore();
177
 
    }
178
 
 
179
 
    if (downloadInfo) {
180
 
        painter->save();
181
 
        QString definitionString = VideoDefinition::getDefinitionName(video->getDefinitionCode());
182
 
        textLoc.setX(textLoc.x() + stringSize.width() + PADDING);
183
 
        stringSize = QSizeF(QFontMetrics(painter->font()).size( Qt::TextSingleLine, definitionString ) );
184
 
        QRectF viewCountTextBox(textLoc , stringSize);
185
 
        painter->drawText(viewCountTextBox, Qt::AlignLeft | Qt::AlignBottom, definitionString);
186
 
        painter->restore();
187
 
    }
188
 
 
189
 
    /*
190
 
    QLinearGradient myGradient;
191
 
    QPen myPen;
192
 
    QFont myFont;
193
 
    QPointF baseline(authorTextBox.x(), authorTextBox.y() + authorTextBox.height());
194
 
    QPainterPath myPath;
195
 
    myPath.addText(baseline, boldFont, authorString);
196
 
    painter->setBrush(palette.color(QPalette::WindowText));
197
 
    painter->setPen(palette.color(QPalette::Dark));
198
 
    painter->setRenderHints (QPainter::Antialiasing, true);
199
 
    painter->drawPath(myPath);
200
 
    */
201
 
 
202
 
    // separator
203
 
    painter->setClipping(false);
204
 
    painter->setPen(option.palette.color(QPalette::Midlight));
205
 
    painter->drawLine(THUMB_WIDTH, THUMB_HEIGHT, option.rect.width(), THUMB_HEIGHT);
206
 
    if (!video->thumbnail().isNull())
207
 
        painter->setPen(Qt::black);
208
 
    painter->drawLine(0, THUMB_HEIGHT, THUMB_WIDTH-1, THUMB_HEIGHT);
209
 
 
210
 
    painter->restore();
211
 
 
212
 
    if (downloadInfo) paintDownloadInfo(painter, option, index);
213
 
 
214
 
}
215
 
 
216
 
void PrettyItemDelegate::paintActiveOverlay( QPainter *painter, qreal x, qreal y, qreal w, qreal h ) const {
217
 
 
218
 
    QPalette palette;
219
 
    QColor highlightColor = palette.color(QPalette::Highlight);
220
 
    QColor backgroundColor = palette.color(QPalette::Base);
221
 
    const float animation = 0.25;
222
 
    const int gradientRange = 16;
223
 
 
224
 
    QColor color2 = QColor::fromHsv(
225
 
            highlightColor.hue(),
226
 
            (int) (backgroundColor.saturation() * (1.0f - animation) + highlightColor.saturation() * animation),
227
 
            (int) (backgroundColor.value() * (1.0f - animation) + highlightColor.value() * animation)
228
 
            );
229
 
    QColor color1 = QColor::fromHsv(
230
 
            color2.hue(),
231
 
            qMax(color2.saturation() - gradientRange, 0),
232
 
            qMin(color2.value() + gradientRange, 255)
233
 
            );
234
 
    QRect rect((int) x, (int) y, (int) w, (int) h);
235
 
    painter->save();
236
 
    painter->setPen(Qt::NoPen);
237
 
    QLinearGradient linearGradient(0, 0, 0, rect.height());
238
 
    linearGradient.setColorAt(0.0, color1);
239
 
    linearGradient.setColorAt(1.0, color2);
240
 
    painter->setBrush(linearGradient);
241
 
    painter->drawRect(rect);
242
 
    painter->restore();
243
 
}
244
 
 
245
 
void PrettyItemDelegate::paintPlayIcon(QPainter *painter) const {
246
 
    painter->save();
247
 
    painter->setOpacity(.5);
248
 
    painter->drawPixmap(playIcon.rect(), playIcon);
249
 
    painter->restore();
250
 
}
251
 
 
252
 
void PrettyItemDelegate::drawTime(QPainter *painter, QString time, QRectF line) const {
253
 
    static const int timePadding = 4;
254
 
    QRectF textBox = painter->boundingRect(line, Qt::AlignLeft | Qt::AlignTop, time);
255
 
    // add padding
256
 
    textBox.adjust(0, 0, timePadding, 0);
257
 
    // move to bottom right corner of the thumb
258
 
    textBox.translate(THUMB_WIDTH - textBox.width(), THUMB_HEIGHT - textBox.height());
259
 
 
260
 
    painter->save();
261
 
    painter->setPen(Qt::NoPen);
262
 
    painter->setBrush(Qt::black);
263
 
    painter->setOpacity(.5);
264
 
    painter->drawRect(textBox);
265
 
    painter->restore();
266
 
 
267
 
    painter->save();
268
 
    painter->setPen(Qt::white);
269
 
    painter->drawText(textBox, Qt::AlignCenter, time);
270
 
    painter->restore();
271
 
}
272
 
 
273
 
void PrettyItemDelegate::paintDownloadInfo( QPainter* painter,
274
 
                                            const QStyleOptionViewItem& option,
275
 
                                            const QModelIndex& index ) const {
276
 
 
277
 
    // get the video metadata
278
 
    const DownloadItemPointer downloadItemPointer = index.data(DownloadItemRole).value<DownloadItemPointer>();
279
 
    const DownloadItem *downloadItem = downloadItemPointer.data();
280
 
 
281
 
    painter->save();
282
 
 
283
 
    const QRect line(0, 0, option.rect.width() / 2, option.rect.height());
284
 
 
285
 
    painter->translate(option.rect.topLeft());
286
 
    painter->translate(line.width(), 0);
287
 
 
288
 
    QString message;
289
 
    DownloadItemStatus status = downloadItem->status();
290
 
 
291
 
    if (status == Downloading) {
292
 
        QString downloaded = DownloadItem::formattedFilesize(downloadItem->bytesReceived());
293
 
        QString total = DownloadItem::formattedFilesize(downloadItem->bytesTotal());
294
 
        QString speed = DownloadItem::formattedSpeed(downloadItem->currentSpeed());
295
 
        QString eta = DownloadItem::formattedTime(downloadItem->remainingTime());
296
 
 
297
 
        message = tr("%1 of %2 (%3) — %4").arg(
298
 
                downloaded,
299
 
                total,
300
 
                speed,
301
 
                eta
302
 
                );
303
 
    } else if (status == Starting) {
304
 
        message = tr("Preparing");
305
 
    } else if (status == Failed) {
306
 
        message = tr("Failed") + " — " + downloadItem->errorMessage();
307
 
    } else if (status == Finished) {
308
 
        message = tr("Completed");
309
 
    } else if (status == Idle) {
310
 
        message = tr("Stopped");
311
 
    }
312
 
 
313
 
    // progressBar->setPalette(option.palette);
314
 
    if (status == Finished) {
315
 
        progressBar->setValue(100);
316
 
        progressBar->setEnabled(true);
317
 
    } else if (status == Downloading) {
318
 
        progressBar->setValue(downloadItem->currentPercent());
319
 
        progressBar->setEnabled(true);
320
 
    } else {
321
 
        progressBar->setValue(0);
322
 
        progressBar->setEnabled(false);
323
 
    }
324
 
 
325
 
    int progressBarWidth = line.width() - PADDING*4 - 16;
326
 
    progressBar->setMaximumWidth(progressBarWidth);
327
 
    progressBar->setMinimumWidth(progressBarWidth);
328
 
    painter->save();
329
 
    painter->translate(PADDING, PADDING);
330
 
    progressBar->render(painter);
331
 
    painter->restore();
332
 
 
333
 
    bool downloadButtonHovered = false;
334
 
    bool downloadButtonPressed = false;
335
 
    const bool isHovered = index.data(HoveredItemRole).toBool();
336
 
    if (isHovered) {
337
 
        downloadButtonHovered = index.data(DownloadButtonHoveredRole).toBool();
338
 
        downloadButtonPressed = index.data(DownloadButtonPressedRole).toBool();
339
 
    }
340
 
    QIcon::Mode iconMode;
341
 
    if (downloadButtonPressed) iconMode = QIcon::Selected;
342
 
    else if (downloadButtonHovered) iconMode = QIcon::Active;
343
 
    else iconMode = QIcon::Normal;
344
 
 
345
 
    if (status != Finished && status != Failed && status != Idle) {
346
 
        if (downloadButtonHovered) message = tr("Stop downloading");
347
 
        painter->save();
348
 
        QIcon closeIcon = QtIconLoader::icon("window-close");
349
 
        painter->drawPixmap(downloadButtonRect(line), closeIcon.pixmap(16, 16, iconMode));
350
 
        painter->restore();
351
 
    }
352
 
 
353
 
    else if (status == Finished) {
354
 
        if (downloadButtonHovered)
355
 
#ifdef APP_MAC
356
 
        message = tr("Show in %1").arg("Finder");
357
 
#else
358
 
        message = tr("Open parent folder");
359
 
#endif
360
 
        painter->save();
361
 
        QIcon searchIcon = QtIconLoader::icon("system-search");
362
 
        painter->drawPixmap(downloadButtonRect(line), searchIcon.pixmap(16, 16, iconMode));
363
 
        painter->restore();
364
 
    }
365
 
 
366
 
    else if (status == Failed || status == Idle) {
367
 
        if (downloadButtonHovered) message = tr("Restart downloading");
368
 
        painter->save();
369
 
        QIcon searchIcon = QtIconLoader::icon("view-refresh");
370
 
        painter->drawPixmap(downloadButtonRect(line), searchIcon.pixmap(16, 16, iconMode));
371
 
        painter->restore();
372
 
    }
373
 
 
374
 
    QRectF textBox = line.adjusted(PADDING, PADDING*2 + progressBar->sizeHint().height(), -2 * PADDING, -PADDING);
375
 
    textBox = painter->boundingRect( textBox, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, message);
376
 
    painter->drawText(textBox, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, message);
377
 
 
378
 
    painter->restore();
379
 
 
380
 
}
381
 
 
382
 
QRect PrettyItemDelegate::downloadButtonRect(QRect line) const {
383
 
    return QRect(
384
 
            line.width() - PADDING*2 - 16,
385
 
            PADDING + progressBar->sizeHint().height() / 2 - 8,
386
 
            16,
387
 
            16);
388
 
}
389
 
 
390
 
QRect PrettyItemDelegate::authorRect(const QModelIndex& index) const {
391
 
    return authorRects.value(index.row());
392
 
}