]> git.sur5r.net Git - minitube/blobdiff - src/playlistitemdelegate.cpp
Merge tag 'upstream/2.1.5'
[minitube] / src / playlistitemdelegate.cpp
index 79b2304afc02475c403fadfa760b686914433fc7..295eba8e403ea5c98498e3f6e055137528a70cd7 100644 (file)
@@ -1,3 +1,23 @@
+/* $BEGIN_LICENSE
+
+This file is part of Minitube.
+Copyright 2009, Flavio Tordini <flavio.tordini@gmail.com>
+
+Minitube is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Minitube is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Minitube.  If not, see <http://www.gnu.org/licenses/>.
+
+$END_LICENSE */
+
 #include "playlistitemdelegate.h"
 #include "playlistmodel.h"
 #include "fontutils.h"
 #include "videodefinition.h"
 #include "video.h"
 
-const qreal PlaylistItemDelegate::THUMB_HEIGHT = 90.0;
-const qreal PlaylistItemDelegate::THUMB_WIDTH = 160.0;
-const qreal PlaylistItemDelegate::PADDING = 10.0;
-
-QRect lastAuthorRect;
-QHash<int, QRect> authorRects;
+const int PlaylistItemDelegate::THUMB_HEIGHT = 90;
+const int PlaylistItemDelegate::THUMB_WIDTH = 160;
+const int PlaylistItemDelegate::PADDING = 10;
 
 PlaylistItemDelegate::PlaylistItemDelegate(QObject* parent, bool downloadInfo)
     : QStyledItemDelegate(parent),
-    downloadInfo(downloadInfo) {
+      downloadInfo(downloadInfo),
+      progressBar(0) {
+
     boldFont.setBold(true);
     smallerBoldFont = FontUtils::smallBold();
     smallerFont = FontUtils::small();
@@ -30,17 +49,26 @@ PlaylistItemDelegate::PlaylistItemDelegate(QObject* parent, bool downloadInfo)
     } else createPlayIcon();
 }
 
+PlaylistItemDelegate::~PlaylistItemDelegate() {
+    if (progressBar) delete progressBar;
+}
+
 void PlaylistItemDelegate::createPlayIcon() {
     playIcon = QPixmap(THUMB_WIDTH, THUMB_HEIGHT);
     playIcon.fill(Qt::transparent);
-    QPainter painter(&playIcon);
-    QPolygon polygon;
+
+    QPixmap tempPixmap(THUMB_WIDTH, THUMB_HEIGHT);
+    tempPixmap.fill(Qt::transparent);
+    QPainter painter(&tempPixmap);
+    painter.setRenderHints(QPainter::Antialiasing, true);
+
     const int hPadding = PADDING*6;
     const int vPadding = PADDING*2;
+
+    QPolygon polygon;
     polygon << QPoint(hPadding, vPadding)
             << QPoint(THUMB_WIDTH-hPadding, THUMB_HEIGHT/2)
             << QPoint(hPadding, THUMB_HEIGHT-vPadding);
-    painter.setRenderHints(QPainter::Antialiasing, true);
     painter.setBrush(Qt::white);
     QPen pen;
     pen.setColor(Qt::white);
@@ -49,16 +77,19 @@ void PlaylistItemDelegate::createPlayIcon() {
     pen.setCapStyle(Qt::RoundCap);
     painter.setPen(pen);
     painter.drawPolygon(polygon);
-}
+    painter.end();
 
-PlaylistItemDelegate::~PlaylistItemDelegate() { }
+    QPainter painter2(&playIcon);
+    painter2.setOpacity(.75);
+    painter2.drawPixmap(0, 0, tempPixmap);
+}
 
 QSize PlaylistItemDelegate::sizeHint( const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/ ) const {
-    return QSize( 256, THUMB_HEIGHT+1.0);
+    return QSize(THUMB_WIDTH, THUMB_HEIGHT + 1);
 }
 
 void PlaylistItemDelegate::paint( QPainter* painter,
-                                const QStyleOptionViewItem& option, const QModelIndex& index ) const {
+                                  const QStyleOptionViewItem& option, const QModelIndex& index ) const {
 
     int itemType = index.data(ItemTypeRole).toInt();
     if (itemType == ItemTypeVideo) {
@@ -73,24 +104,20 @@ void PlaylistItemDelegate::paint( QPainter* painter,
 }
 
 void PlaylistItemDelegate::paintBody( QPainter* painter,
-                                    const QStyleOptionViewItem& option,
-                                    const QModelIndex& index ) const {
-
+                                      const QStyleOptionViewItem& option,
+                                      const QModelIndex& index ) const {
     painter->save();
     painter->translate( option.rect.topLeft() );
 
-
-    QRectF line(0, 0, option.rect.width(), option.rect.height());
+    QRect line(0, 0, option.rect.width(), option.rect.height());
     if (downloadInfo) line.setWidth(line.width() / 2);
-    painter->setClipRect(line);
 
     const bool isActive = index.data( ActiveTrackRole ).toBool();
     const bool isSelected = option.state & QStyle::State_Selected;
 
     // draw the "current track" highlight underneath the text
-    if (isActive && !isSelected) {
-        paintActiveOverlay(painter, line.x(), line.y(), line.width(), line.height());
-    }
+    if (isActive && !isSelected)
+        paintActiveOverlay(painter, line);
 
     // get the video metadata
     const VideoPointer videoPointer = index.data( VideoRole ).value<VideoPointer>();
@@ -101,101 +128,124 @@ void PlaylistItemDelegate::paintBody( QPainter* painter,
 
     // play icon overlayed on the thumb
     if (isActive)
-        paintPlayIcon(painter);
+        painter->drawPixmap(playIcon.rect(), playIcon);
 
     // time
     drawTime(painter, video->formattedDuration(), line);
 
-    if (isActive) painter->setFont(boldFont);
-
-    // text color
-    if (isSelected)
-        painter->setPen(QPen(option.palette.brush(QPalette::HighlightedText), 0));
-    else
-        painter->setPen(QPen(option.palette.brush(QPalette::Text), 0));
-
-    // title
-    QString videoTitle = video->title();
-    QRectF textBox = line.adjusted(PADDING+THUMB_WIDTH, PADDING, -2 * PADDING, -PADDING);
-    textBox = painter->boundingRect( textBox, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, videoTitle);
-    painter->drawText(textBox, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, videoTitle);
-
-    painter->setFont(smallerFont);
+    // separator
+    painter->setPen(option.palette.color(QPalette::Midlight));
+    painter->drawLine(THUMB_WIDTH, THUMB_HEIGHT, option.rect.width(), THUMB_HEIGHT);
+    if (!video->thumbnail().isNull())
+        painter->setPen(Qt::black);
+    painter->drawLine(0, THUMB_HEIGHT, THUMB_WIDTH-1, THUMB_HEIGHT);
 
-    // published date
-    QString publishedString = video->published().date().toString(Qt::DefaultLocaleShortDate);
-    QSizeF stringSize(QFontMetrics(painter->font()).size( Qt::TextSingleLine, publishedString ) );
-    QPointF textLoc(PADDING+THUMB_WIDTH, PADDING*2 + textBox.height());
-    QRectF publishedTextBox(textLoc , stringSize);
-    painter->drawText(publishedTextBox, Qt::AlignLeft | Qt::AlignTop, publishedString);
+    if (line.width() > THUMB_WIDTH + 60) {
 
-    // author
-    bool authorHovered = false;
-    bool authorPressed = false;
-    const bool isHovered = index.data(HoveredItemRole).toBool();
-    if (isHovered) {
-        authorHovered = index.data(AuthorHoveredRole).toBool();
-        authorPressed = index.data(AuthorPressedRole).toBool();
-    }
+        if (isActive) painter->setFont(boldFont);
 
-    painter->save();
-    painter->setFont(smallerBoldFont);
-    if (!isSelected) {
-        if (authorHovered)
-            painter->setPen(QPen(option.palette.brush(QPalette::Highlight), 0));
+        // text color
+        if (isSelected)
+            painter->setPen(QPen(option.palette.brush(QPalette::HighlightedText), 0));
         else
-            painter->setPen(QPen(option.palette.brush(QPalette::Mid), 0));
-    }
-    QString authorString = video->author();
-    textLoc.setX(textLoc.x() + stringSize.width() + PADDING);
-    stringSize = QSizeF(QFontMetrics(painter->font()).size( Qt::TextSingleLine, authorString ) );
-    QRectF authorTextBox(textLoc , stringSize);
-    authorRects.insert(index.row(), authorTextBox.toRect());
-    painter->drawText(authorTextBox, Qt::AlignLeft | Qt::AlignTop, authorString);
-    painter->restore();
-
-    // view count
-    if (video->viewCount() >= 0) {
-        painter->save();
-        QLocale locale;
-        QString viewCountString = tr("%1 views").arg(locale.toString(video->viewCount()));
-        textLoc.setX(textLoc.x() + stringSize.width() + PADDING);
-        stringSize = QSizeF(QFontMetrics(painter->font()).size( Qt::TextSingleLine, viewCountString ) );
-        QRectF viewCountTextBox(textLoc , stringSize);
-        painter->drawText(viewCountTextBox, Qt::AlignLeft | Qt::AlignBottom, viewCountString);
-        painter->restore();
-    }
+            painter->setPen(QPen(option.palette.brush(QPalette::Text), 0));
+
+        // title
+        QString videoTitle = video->title();
+        QString v = videoTitle;
+        const int flags = Qt::AlignTop | Qt::TextWordWrap;
+        QRect textBox = line.adjusted(PADDING+THUMB_WIDTH, PADDING, 0, 0);
+        textBox = painter->boundingRect(textBox, flags, v);
+        while (textBox.height() > 55 && v.length() > 10) {
+            videoTitle.truncate(videoTitle.length() - 1);
+            v = videoTitle;
+            v = v.trimmed().append("...");
+            textBox = painter->boundingRect(textBox, flags, v);
+        }
+        painter->drawText(textBox, flags, v);
+
+        painter->setFont(smallerFont);
+
+        // published date
+        QString publishedString = video->published().date().toString(Qt::DefaultLocaleShortDate);
+        QSize stringSize(QFontMetrics(painter->font()).size( Qt::TextSingleLine, publishedString ) );
+        QPoint textLoc(PADDING+THUMB_WIDTH, PADDING*2 + textBox.height());
+        QRect publishedTextBox(textLoc , stringSize);
+        painter->drawText(publishedTextBox, Qt::AlignLeft | Qt::AlignTop, publishedString);
+
+        if (line.width() > publishedTextBox.x() + publishedTextBox.width()*2) {
+
+            // author
+            bool authorHovered = false;
+            bool authorPressed = false;
+            const bool isHovered = index.data(HoveredItemRole).toBool();
+            if (isHovered) {
+                authorHovered = index.data(AuthorHoveredRole).toBool();
+                authorPressed = index.data(AuthorPressedRole).toBool();
+            }
+
+            painter->save();
+            painter->setFont(smallerBoldFont);
+            if (!isSelected) {
+                if (authorHovered)
+                    painter->setPen(QPen(option.palette.brush(QPalette::Highlight), 0));
+                else
+                    painter->setPen(QPen(option.palette.brush(QPalette::Mid), 0));
+            }
+            QString authorString = video->author();
+            textLoc.setX(textLoc.x() + stringSize.width() + PADDING);
+            stringSize = QSize(QFontMetrics(painter->font()).size( Qt::TextSingleLine, authorString ) );
+            QRect authorTextBox(textLoc , stringSize);
+            authorRects.insert(index.row(), authorTextBox);
+            painter->drawText(authorTextBox, Qt::AlignLeft | Qt::AlignTop, authorString);
+            painter->restore();
+
+            if (line.width() > authorTextBox.x() + 50) {
+
+                // view count
+                if (video->viewCount() >= 0) {
+                    QLocale locale;
+                    QString viewCountString = tr("%1 views").arg(locale.toString(video->viewCount()));
+                    textLoc.setX(textLoc.x() + stringSize.width() + PADDING);
+                    stringSize = QSize(QFontMetrics(painter->font()).size( Qt::TextSingleLine, viewCountString ) );
+                    QRect viewCountTextBox(textLoc , stringSize);
+                    painter->drawText(viewCountTextBox, Qt::AlignLeft | Qt::AlignBottom, viewCountString);
+                }
+
+                if (downloadInfo) {
+                    QString definitionString = VideoDefinition::getDefinitionName(video->getDefinitionCode());
+                    textLoc.setX(textLoc.x() + stringSize.width() + PADDING);
+                    stringSize = QSize(QFontMetrics(painter->font()).size( Qt::TextSingleLine, definitionString ) );
+                    QRect viewCountTextBox(textLoc , stringSize);
+                    painter->drawText(viewCountTextBox, Qt::AlignLeft | Qt::AlignBottom, definitionString);
+                }
+
+            }
+
+        }
 
-    if (downloadInfo) {
-        painter->save();
-        QString definitionString = VideoDefinition::getDefinitionName(video->getDefinitionCode());
-        textLoc.setX(textLoc.x() + stringSize.width() + PADDING);
-        stringSize = QSizeF(QFontMetrics(painter->font()).size( Qt::TextSingleLine, definitionString ) );
-        QRectF viewCountTextBox(textLoc , stringSize);
-        painter->drawText(viewCountTextBox, Qt::AlignLeft | Qt::AlignBottom, definitionString);
-        painter->restore();
-    }
+    } else {
 
-    /*
-    QLinearGradient myGradient;
-    QPen myPen;
-    QFont myFont;
-    QPointF baseline(authorTextBox.x(), authorTextBox.y() + authorTextBox.height());
-    QPainterPath myPath;
-    myPath.addText(baseline, boldFont, authorString);
-    painter->setBrush(palette.color(QPalette::WindowText));
-    painter->setPen(palette.color(QPalette::Dark));
-    painter->setRenderHints (QPainter::Antialiasing, true);
-    painter->drawPath(myPath);
-    */
+        bool isHovered = option.state & QStyle::State_MouseOver;
+        if (!isActive && isHovered) {
+            painter->setFont(smallerFont);
+            painter->setPen(Qt::white);
+            QString videoTitle = video->title();
+            QString v = videoTitle;
+            const int flags = Qt::AlignTop | Qt::TextWordWrap;
+            QRect textBox(PADDING, PADDING, THUMB_WIDTH - PADDING*2, THUMB_HEIGHT - PADDING*2);
+            textBox = painter->boundingRect(textBox, flags, v);
+            while (textBox.height() > THUMB_HEIGHT && v.length() > 10) {
+                videoTitle.truncate(videoTitle.length() - 1);
+                v = videoTitle;
+                v = v.trimmed().append("...");
+                textBox = painter->boundingRect(textBox, flags, v);
+            }
+            painter->fillRect(QRect(0, 0, THUMB_WIDTH, textBox.height() + PADDING*2), QColor(0, 0, 0, 128));
+            painter->drawText(textBox, flags, v);
+        }
 
-    // separator
-    painter->setClipping(false);
-    painter->setPen(option.palette.color(QPalette::Midlight));
-    painter->drawLine(THUMB_WIDTH, THUMB_HEIGHT, option.rect.width(), THUMB_HEIGHT);
-    if (!video->thumbnail().isNull())
-        painter->setPen(Qt::black);
-    painter->drawLine(0, THUMB_HEIGHT, THUMB_WIDTH-1, THUMB_HEIGHT);
+    }
 
     painter->restore();
 
@@ -203,45 +253,40 @@ void PlaylistItemDelegate::paintBody( QPainter* painter,
 
 }
 
-void PlaylistItemDelegate::paintActiveOverlay( QPainter *painter, qreal x, qreal y, qreal w, qreal h ) const {
-
-    QPalette palette;
-    QColor highlightColor = palette.color(QPalette::Highlight);
-    QColor backgroundColor = palette.color(QPalette::Base);
-    const float animation = 0.25;
-    const int gradientRange = 16;
-
-    QColor color2 = QColor::fromHsv(
-            highlightColor.hue(),
-            (int) (backgroundColor.saturation() * (1.0f - animation) + highlightColor.saturation() * animation),
-            (int) (backgroundColor.value() * (1.0f - animation) + highlightColor.value() * animation)
-            );
-    QColor color1 = QColor::fromHsv(
-            color2.hue(),
-            qMax(color2.saturation() - gradientRange, 0),
-            qMin(color2.value() + gradientRange, 255)
-            );
-    QRect rect((int) x, (int) y, (int) w, (int) h);
-    painter->save();
-    painter->setPen(Qt::NoPen);
-    QLinearGradient linearGradient(0, 0, 0, rect.height());
-    linearGradient.setColorAt(0.0, color1);
-    linearGradient.setColorAt(1.0, color2);
-    painter->setBrush(linearGradient);
-    painter->drawRect(rect);
-    painter->restore();
-}
+void PlaylistItemDelegate::paintActiveOverlay(QPainter *painter, const QRect &line) const {
+    static QLinearGradient linearGradient;
+    static bool initialized = false;
+
+    if (!initialized) {
+        QPalette palette;
+        QColor highlightColor = palette.color(QPalette::Highlight);
+        QColor backgroundColor = palette.color(QPalette::Base);
+        const float animation = 0.4;
+        const int gradientRange = 16;
+
+        QColor color2 = QColor::fromHsv(
+                    highlightColor.hue(),
+                    (int) (backgroundColor.saturation() * (1.0f - animation) + highlightColor.saturation() * animation),
+                    (int) (backgroundColor.value() * (1.0f - animation) + highlightColor.value() * animation)
+                    );
+        QColor color1 = QColor::fromHsv(
+                    color2.hue(),
+                    qMax(color2.saturation() - gradientRange, 0),
+                    qMin(color2.value() + gradientRange, 255)
+                    );
+
+        linearGradient = QLinearGradient(0, 0, 0, THUMB_HEIGHT);
+        linearGradient.setColorAt(0.0, color1);
+        linearGradient.setColorAt(1.0, color2);
+        initialized = true;
+    }
 
-void PlaylistItemDelegate::paintPlayIcon(QPainter *painter) const {
-    painter->save();
-    painter->setOpacity(.5);
-    painter->drawPixmap(playIcon.rect(), playIcon);
-    painter->restore();
+    painter->fillRect(line, linearGradient);
 }
 
-void PlaylistItemDelegate::drawTime(QPainter *painter, QString time, QRectF line) const {
+void PlaylistItemDelegate::drawTime(QPainter *painter, const QString &time, const QRect &line) const {
     static const int timePadding = 4;
-    QRectF textBox = painter->boundingRect(line, Qt::AlignLeft | Qt::AlignTop, time);
+    QRect textBox = painter->boundingRect(line, Qt::AlignLeft | Qt::AlignTop, time);
     // add padding
     textBox.adjust(0, 0, timePadding, 0);
     // move to bottom right corner of the thumb
@@ -261,8 +306,8 @@ void PlaylistItemDelegate::drawTime(QPainter *painter, QString time, QRectF line
 }
 
 void PlaylistItemDelegate::paintDownloadInfo( QPainter* painter,
-                                            const QStyleOptionViewItem& option,
-                                            const QModelIndex& index ) const {
+                                              const QStyleOptionViewItem& option,
+                                              const QModelIndex& index ) const {
 
     // get the video metadata
     const DownloadItemPointer downloadItemPointer = index.data(DownloadItemRole).value<DownloadItemPointer>();
@@ -285,11 +330,11 @@ void PlaylistItemDelegate::paintDownloadInfo( QPainter* painter,
         QString eta = DownloadItem::formattedTime(downloadItem->remainingTime());
 
         message = tr("%1 of %2 (%3) — %4").arg(
-                downloaded,
-                total,
-                speed,
-                eta
-                );
+                    downloaded,
+                    total,
+                    speed,
+                    eta
+                    );
     } else if (status == Starting) {
         message = tr("Preparing");
     } else if (status == Failed) {
@@ -343,9 +388,9 @@ void PlaylistItemDelegate::paintDownloadInfo( QPainter* painter,
     else if (status == Finished) {
         if (downloadButtonHovered)
 #ifdef APP_MAC
-        message = tr("Show in %1").arg("Finder");
+            message = tr("Show in %1").arg("Finder");
 #else
-        message = tr("Open parent folder");
+            message = tr("Open parent folder");
 #endif
         painter->save();
         QIcon searchIcon = Utils::icon("system-search");
@@ -361,20 +406,19 @@ void PlaylistItemDelegate::paintDownloadInfo( QPainter* painter,
         painter->restore();
     }
 
-    QRectF textBox = line.adjusted(PADDING, PADDING*2 + progressBar->sizeHint().height(), -2 * PADDING, -PADDING);
+    QRect textBox = line.adjusted(PADDING, PADDING*2 + progressBar->sizeHint().height(), -2 * PADDING, -PADDING);
     textBox = painter->boundingRect( textBox, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, message);
     painter->drawText(textBox, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, message);
 
     painter->restore();
-
 }
 
-QRect PlaylistItemDelegate::downloadButtonRect(QRect line) const {
+QRect PlaylistItemDelegate::downloadButtonRect(const QRect &line) const {
     return QRect(
-            line.width() - PADDING*2 - 16,
-            PADDING + progressBar->sizeHint().height() / 2 - 8,
-            16,
-            16);
+                line.width() - PADDING*2 - 16,
+                PADDING + progressBar->sizeHint().height() / 2 - 8,
+                16,
+                16);
 }
 
 QRect PlaylistItemDelegate::authorRect(const QModelIndex& index) const {