]> cloud.milkyroute.net Git - dolphin.git/blob - src/dolphincategorydrawer.cpp
Prettier category drawing :)
[dolphin.git] / src / dolphincategorydrawer.cpp
1 /**
2 * This file is part of the KDE project
3 * Copyright (C) 2007 Rafael Fernández López <ereslibre@gmail.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include "dolphincategorydrawer.h"
22
23 #include <QPainter>
24 #include <QFile>
25 #include <QDir>
26
27 #include <kiconloader.h>
28 #include <kcategorizedsortfilterproxymodel.h>
29 #include <kpixmapeffect.h>
30 #include <kuser.h>
31
32 #include <config-nepomuk.h>
33 #ifdef HAVE_NEPOMUK
34 #include <nepomuk/global.h>
35 #include <nepomuk/resource.h>
36 #include <nepomuk/tag.h>
37 #endif
38
39 #include "dolphinview.h"
40 #include "dolphinmodel.h"
41
42 DolphinCategoryDrawer::DolphinCategoryDrawer()
43 {
44 }
45
46 DolphinCategoryDrawer::~DolphinCategoryDrawer()
47 {
48 }
49
50 void DolphinCategoryDrawer::drawCategory(const QModelIndex &index, int sortRole,
51 const QStyleOption &option, QPainter *painter) const
52 {
53 QRect starRect = option.rect;
54
55 int iconSize = KIconLoader::global()->currentSize(K3Icon::Small);
56 QVariant categoryVariant = index.model()->data(index, KCategorizedSortFilterProxyModel::CategoryRole);
57
58 if (!categoryVariant.isValid())
59 {
60 return;
61 }
62
63 const QString category = categoryVariant.toString();
64
65 QColor color;
66
67 if (option.state & QStyle::State_Selected)
68 {
69 color = option.palette.color(QPalette::HighlightedText);
70 }
71 else
72 {
73 color = option.palette.color(QPalette::Text);
74 }
75
76 painter->save();
77 painter->setRenderHint(QPainter::Antialiasing);
78
79 QStyleOptionButton opt;
80
81 opt.rect = option.rect;
82 opt.palette = option.palette;
83 opt.direction = option.direction;
84 opt.text = category;
85
86 if (option.state & QStyle::State_Selected)
87 {
88 QColor selected = option.palette.color(QPalette::Highlight);
89
90 QLinearGradient gradient(option.rect.topLeft(),
91 option.rect.bottomRight());
92 gradient.setColorAt(option.direction == Qt::LeftToRight ? 0
93 : 1, selected);
94 gradient.setColorAt(option.direction == Qt::LeftToRight ? 1
95 : 0, Qt::transparent);
96
97 painter->fillRect(option.rect, gradient);
98 }
99 else if (option.state & QStyle::State_MouseOver)
100 {
101 QColor hover = option.palette.color(QPalette::Highlight).light();
102 hover.setAlpha(88);
103
104 QLinearGradient gradient(option.rect.topLeft(),
105 option.rect.bottomRight());
106 gradient.setColorAt(option.direction == Qt::LeftToRight ? 0
107 : 1, hover);
108 gradient.setColorAt(option.direction == Qt::LeftToRight ? 1
109 : 0, Qt::transparent);
110
111 painter->fillRect(option.rect, gradient);
112 }
113
114 QFont painterFont = painter->font();
115 painterFont.setWeight(QFont::Bold);
116 QFontMetrics metrics(painterFont);
117 painter->setFont(painterFont);
118
119 QPainterPath path;
120 path.addRect(option.rect.left(),
121 option.rect.bottom() - 2,
122 option.rect.width(),
123 2);
124
125 QLinearGradient gradient(option.rect.topLeft(),
126 option.rect.bottomRight());
127 gradient.setColorAt(option.direction == Qt::LeftToRight ? 0
128 : 1, color);
129 gradient.setColorAt(option.direction == Qt::LeftToRight ? 1
130 : 0, Qt::transparent);
131
132 painter->setBrush(gradient);
133 painter->fillPath(path, gradient);
134
135 if (option.direction == Qt::LeftToRight)
136 {
137 opt.rect.setLeft(opt.rect.left() + (iconSize / 4));
138 starRect.setLeft(starRect.left() + (iconSize / 4));
139 starRect.setRight(starRect.right() + (iconSize / 4));
140 }
141 else
142 {
143 opt.rect.setRight(opt.rect.width() - (iconSize / 4));
144 starRect.setLeft(starRect.width() - iconSize);
145 starRect.setRight(starRect.width() - (iconSize / 4));
146 }
147
148 bool paintIcon = true;
149 bool paintText = true;
150
151 QPixmap icon;
152 switch (index.column()) {
153 case KDirModel::Name:
154 paintIcon = false;
155 break;
156
157 case KDirModel::Size:
158 paintIcon = false;
159 break;
160
161 case KDirModel::ModifiedTime:
162 paintIcon = false;
163 break;
164
165 case KDirModel::Permissions:
166 paintIcon = false; // TODO: let's think about how to represent permissions
167 break;
168
169 case KDirModel::Owner: {
170 opt.rect.setTop(option.rect.bottom() - (iconSize / 4));
171 KUser user(category);
172 QString faceIconPath = user.faceIconPath();
173
174 if (!faceIconPath.isEmpty())
175 {
176 icon = QPixmap::fromImage(QImage(faceIconPath).scaledToHeight(option.fontMetrics.height(), Qt::SmoothTransformation));
177 }
178 else
179 {
180 icon = KIconLoader::global()->loadIcon("user", K3Icon::NoGroup, option.fontMetrics.height());
181 }
182
183 opt.rect.setTop(opt.rect.top() - icon.height());
184
185 break;
186 }
187
188 case KDirModel::Group:
189 paintIcon = false;
190 break;
191
192 case KDirModel::Type: {
193 opt.rect.setTop(option.rect.bottom() - (iconSize / 4));
194 const KCategorizedSortFilterProxyModel *proxyModel = static_cast<const KCategorizedSortFilterProxyModel*>(index.model());
195 const DolphinModel *model = static_cast<const DolphinModel*>(proxyModel->sourceModel());
196 KFileItem item = model->itemForIndex(proxyModel->mapToSource(index));
197 // This is the only way of getting the icon right. Others will fail on corner
198 // cases like the item representing this group has been set a different icon,
199 // so the group icon drawn is that one particularly. This way assures the drawn
200 // icon is the one of the mimetype of the group itself. (ereslibre)
201 icon = KIconLoader::global()->loadMimeTypeIcon(item.mimeTypePtr()->iconName(),
202 K3Icon::NoGroup, option.fontMetrics.height());
203
204 opt.rect.setTop(opt.rect.top() - icon.height());
205
206 break;
207 }
208
209 #ifdef HAVE_NEPOMUK
210 case DolphinModel::Rating: {
211 paintText = false;
212 paintIcon = false;
213
214 starRect.setTop(option.rect.top() + (option.rect.height() / 2) - (iconSize / 2));
215 starRect.setSize(QSize(iconSize, iconSize));
216
217 QPixmap pixmap = KIconLoader::global()->loadIcon("rating", K3Icon::Small);
218 QPixmap smallPixmap = KIconLoader::global()->loadIcon("rating", K3Icon::NoGroup, iconSize / 2);
219 QPixmap disabledPixmap = KIconLoader::global()->loadIcon("rating", K3Icon::Small);
220
221 KPixmapEffect::toGray(disabledPixmap, false);
222
223 int rating = category.toInt();
224
225 for (int i = 0; i < rating - (rating % 2); i += 2) {
226 painter->drawPixmap(starRect, pixmap);
227
228 if (option.direction == Qt::LeftToRight)
229 {
230 starRect.setLeft(starRect.left() + iconSize + (iconSize / 4) /* separator between stars */);
231 starRect.setRight(starRect.right() + iconSize + (iconSize / 4) /* separator between stars */);
232 }
233 else
234 {
235 starRect.setLeft(starRect.left() - iconSize - (iconSize / 4) /* separator between stars */);
236 starRect.setRight(starRect.right() - iconSize - (iconSize / 4) /* separator between stars */);
237 }
238 }
239
240 if (rating && rating % 2) {
241 if (option.direction == Qt::RightToLeft)
242 {
243 starRect.setLeft(starRect.left() + (iconSize / 2) /* separator between stars */);
244 }
245
246 starRect.setTop(option.rect.top() + (option.rect.height() / 2) - (iconSize / 4));
247 starRect.setSize(QSize(iconSize / 2, iconSize / 2));
248 painter->drawPixmap(starRect, smallPixmap);
249 starRect.setTop(opt.rect.top() + (option.rect.height() / 2) - (iconSize / 2));
250
251 if (option.direction == Qt::LeftToRight)
252 {
253 starRect.setLeft(starRect.left() + (iconSize / 2) + (iconSize / 4));
254 starRect.setRight(starRect.right() + (iconSize / 2) + (iconSize / 4));
255 }
256 else
257 {
258 starRect.setLeft(starRect.left() - (iconSize / 2) - (iconSize / 4));
259 starRect.setRight(starRect.right() - (iconSize / 2) - (iconSize / 4));
260 }
261
262 if (option.direction == Qt::RightToLeft)
263 {
264 starRect.setLeft(starRect.left() - (iconSize / 2));
265 starRect.setRight(starRect.right() - (iconSize / 2));
266 }
267
268 starRect.setSize(QSize(iconSize, iconSize));
269 }
270
271 for (int i = rating; i < 9; i += 2) {
272 painter->drawPixmap(starRect, disabledPixmap);
273
274 if (option.direction == Qt::LeftToRight)
275 {
276 starRect.setLeft(starRect.left() + iconSize + (iconSize / 4));
277 starRect.setRight(starRect.right() + iconSize + (iconSize / 4));
278 }
279 else
280 {
281 starRect.setLeft(starRect.left() - iconSize - (iconSize / 4));
282 starRect.setRight(starRect.right() - iconSize - (iconSize / 4));
283 }
284 }
285
286 break;
287 }
288
289 case DolphinModel::Tags:
290 paintIcon = false;
291 break;
292 #endif
293 }
294
295 if (paintIcon) {
296 painter->drawPixmap(QRect(option.direction == Qt::LeftToRight ? opt.rect.left()
297 : opt.rect.right() - icon.width() + (iconSize / 4), opt.rect.top(), icon.width(), icon.height()), icon);
298
299 if (option.direction == Qt::LeftToRight)
300 {
301 opt.rect.setLeft(opt.rect.left() + icon.width() + (iconSize / 4));
302 }
303 else
304 {
305 opt.rect.setRight(opt.rect.right() + (iconSize / 4));
306 }
307 }
308
309 if (paintText) {
310 opt.rect.setTop(option.rect.top() + (iconSize / 4));
311 opt.rect.setBottom(opt.rect.bottom() - 2);
312 painter->setPen(color);
313
314 QRect textRect = opt.rect;
315
316 if (option.direction == Qt::RightToLeft)
317 {
318 textRect.setWidth(textRect.width() - (paintIcon ? icon.width() + (iconSize / 2)
319 : -(iconSize / 4)));
320 }
321
322 painter->drawText(textRect, Qt::AlignVCenter | Qt::AlignLeft,
323 metrics.elidedText(category, Qt::ElideRight, textRect.width()));
324 }
325
326 painter->restore();
327 }
328
329 int DolphinCategoryDrawer::categoryHeight(const QStyleOption &option) const
330 {
331 int iconSize = KIconLoader::global()->currentSize(K3Icon::Small);
332
333 return qMax(option.fontMetrics.height() + (iconSize / 4) * 2 + 2, iconSize + (iconSize / 4) * 2 + 2) /* 2 gradient */;
334 }