1 /*
2 * Strawberry Music Player
3 * This file was part of Clementine.
4 * Copyright 2010, David Sansome <me@davidsansome.com>
5 * Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
6 *
7 * Strawberry is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * Strawberry is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22 #include "config.h"
23
24 #include <QtGlobal>
25 #include <QAbstractItemModel>
26 #include <QAbstractItemView>
27 #include <QStyleOptionViewItem>
28 #include <QVariant>
29 #include <QString>
30 #include <QLocale>
31 #include <QPixmap>
32 #include <QIcon>
33 #include <QPainter>
34 #include <QPalette>
35 #include <QPen>
36 #include <QRect>
37 #include <QSize>
38 #include <QBrush>
39 #include <QColor>
40 #include <QFont>
41 #include <QPoint>
42 #include <QLinearGradient>
43 #include <QToolTip>
44 #include <QWhatsThis>
45 #include <QtEvents>
46
47 #include "collectionitemdelegate.h"
48 #include "collectionmodel.h"
49
CollectionItemDelegate(QObject * parent)50 CollectionItemDelegate::CollectionItemDelegate(QObject *parent) : QStyledItemDelegate(parent) {}
51
paint(QPainter * painter,const QStyleOptionViewItem & opt,const QModelIndex & idx) const52 void CollectionItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opt, const QModelIndex &idx) const {
53
54 const bool is_divider = idx.data(CollectionModel::Role_IsDivider).toBool();
55
56 if (is_divider) {
57 QString text(idx.data().toString());
58
59 painter->save();
60
61 QRect text_rect(opt.rect);
62
63 // Does this item have an icon?
64 QPixmap pixmap;
65 QVariant decoration = idx.data(Qt::DecorationRole);
66 if (!decoration.isNull()) {
67 if (decoration.canConvert<QPixmap>()) {
68 pixmap = decoration.value<QPixmap>();
69 }
70 else if (decoration.canConvert<QIcon>()) {
71 pixmap = decoration.value<QIcon>().pixmap(opt.decorationSize);
72 }
73 }
74
75 // Draw the icon at the left of the text rectangle
76 if (!pixmap.isNull()) {
77 QRect icon_rect(text_rect.topLeft(), opt.decorationSize);
78 const int padding = (text_rect.height() - icon_rect.height()) / 2;
79 icon_rect.adjust(padding, padding, padding, padding);
80 text_rect.moveLeft(icon_rect.right() + padding + 6);
81
82 if (pixmap.size() != opt.decorationSize) {
83 pixmap = pixmap.scaled(opt.decorationSize, Qt::KeepAspectRatio);
84 }
85
86 painter->drawPixmap(icon_rect, pixmap);
87 }
88 else {
89 text_rect.setLeft(text_rect.left() + 30);
90 }
91
92 // Draw the text
93 QFont bold_font(opt.font);
94 bold_font.setBold(true);
95
96 painter->setPen(opt.palette.color(QPalette::Text));
97 painter->setFont(bold_font);
98 painter->drawText(text_rect, text);
99
100 // Draw the line under the item
101 QColor line_color = opt.palette.color(QPalette::Text);
102 QLinearGradient grad_color(opt.rect.bottomLeft(), opt.rect.bottomRight());
103 const double fade_start_end = (opt.rect.width()/3.0)/opt.rect.width();
104 line_color.setAlphaF(0.0);
105 grad_color.setColorAt(0, line_color);
106 line_color.setAlphaF(0.5);
107 grad_color.setColorAt(fade_start_end, line_color);
108 grad_color.setColorAt(1.0 - fade_start_end, line_color);
109 line_color.setAlphaF(0.0);
110 grad_color.setColorAt(1, line_color);
111 painter->setPen(QPen(grad_color, 1));
112 painter->drawLine(opt.rect.bottomLeft(), opt.rect.bottomRight());
113
114 painter->restore();
115 }
116 else {
117 QStyledItemDelegate::paint(painter, opt, idx);
118 }
119
120 }
121
helpEvent(QHelpEvent * event,QAbstractItemView * view,const QStyleOptionViewItem & option,const QModelIndex & idx)122 bool CollectionItemDelegate::helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &idx) {
123
124 Q_UNUSED(option);
125
126 if (!event || !view) return false;
127
128 QString text = displayText(idx.data(), QLocale::system());
129
130 if (text.isEmpty() || !event) return false;
131
132 switch (event->type()) {
133 case QEvent::ToolTip: {
134
135 QSize real_text = sizeHint(option, idx);
136 QRect displayed_text = view->visualRect(idx);
137 bool is_elided = displayed_text.width() < real_text.width();
138
139 if (is_elided) {
140 QToolTip::showText(event->globalPos(), text, view);
141 }
142 else if (idx.data(Qt::ToolTipRole).isValid()) {
143 // If the item has a tooltip text, display it
144 QString tooltip_text = idx.data(Qt::ToolTipRole).toString();
145 QToolTip::showText(event->globalPos(), tooltip_text, view);
146 }
147 else {
148 // in case that another text was previously displayed
149 QToolTip::hideText();
150 }
151 return true;
152 }
153
154 case QEvent::QueryWhatsThis:
155 return true;
156
157 case QEvent::WhatsThis:
158 QWhatsThis::showText(event->globalPos(), text, view);
159 return true;
160
161 default:
162 break;
163 }
164 return false;
165
166 }
167