2 * This file is part of the KDE project
3 * Copyright (C) 2007 Rafael Fernández López <ereslibre@kde.org>
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.
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.
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.
21 #include "dolphincategorydrawer.h"
23 #include <config-nepomuk.h>
28 #include <QApplication>
29 #include <QStyleOption>
32 #include <nepomuk/kratingpainter.h>
35 #include <kiconloader.h>
36 #include <kiconeffect.h>
37 #include <kcategorizedsortfilterproxymodel.h>
38 #include <qimageblitz.h>
40 #include <kcategorizedview.h>
42 #include "dolphinview.h"
43 #include "dolphinmodel.h"
45 #define HORIZONTAL_HINT 3
47 DolphinCategoryDrawer::DolphinCategoryDrawer(KCategorizedView
*view
)
48 : KCategoryDrawerV3(view
)
49 , hotSpotPressed(NoneHotSpot
)
50 , selectAll(KIconLoader::global()->loadIcon("list-add", KIconLoader::Desktop
, 16))
51 , selectAllHovered(KIconLoader::global()->iconEffect()->apply(selectAll
, KIconLoader::Desktop
, KIconLoader::ActiveState
))
52 , selectAllDisabled(KIconLoader::global()->iconEffect()->apply(selectAll
, KIconLoader::Desktop
, KIconLoader::DisabledState
))
53 , unselectAll(KIconLoader::global()->loadIcon("list-remove", KIconLoader::Desktop
, 16))
54 , unselectAllHovered(KIconLoader::global()->iconEffect()->apply(unselectAll
, KIconLoader::Desktop
, KIconLoader::ActiveState
))
55 , unselectAllDisabled(KIconLoader::global()->iconEffect()->apply(unselectAll
, KIconLoader::Desktop
, KIconLoader::DisabledState
))
59 DolphinCategoryDrawer::~DolphinCategoryDrawer()
63 bool DolphinCategoryDrawer::allCategorySelected(const QString
&category
) const
65 const QModelIndexList list
= view()->block(category
);
66 foreach (const QModelIndex
&index
, list
) {
67 if (!view()->selectionModel()->isSelected(index
)) {
74 bool DolphinCategoryDrawer::someCategorySelected(const QString
&category
) const
76 const QModelIndexList list
= view()->block(category
);
77 foreach (const QModelIndex
&index
, list
) {
78 if (view()->selectionModel()->isSelected(index
)) {
85 void DolphinCategoryDrawer::drawCategory(const QModelIndex
&index
, int sortRole
,
86 const QStyleOption
&option
, QPainter
*painter
) const
89 painter
->setRenderHint(QPainter::Antialiasing
);
91 if (!index
.isValid()) {
95 const QString category
= index
.model()->data(index
, KCategorizedSortFilterProxyModel::CategoryDisplayRole
).toString();
96 const QRect optRect
= option
.rect
;
97 QFont
font(QApplication::font());
99 const QFontMetrics fontMetrics
= QFontMetrics(font
);
101 QColor outlineColor
= option
.palette
.text().color();
102 outlineColor
.setAlphaF(0.35);
104 //BEGIN: top left corner
107 painter
->setPen(outlineColor
);
108 const QPointF
topLeft(optRect
.topLeft());
109 QRectF
arc(topLeft
, QSizeF(4, 4));
110 arc
.translate(0.5, 0.5);
111 painter
->drawArc(arc
, 1440, 1440);
114 //END: top left corner
116 //BEGIN: left vertical line
118 QPoint
start(optRect
.topLeft());
120 QPoint
verticalGradBottom(optRect
.topLeft());
121 verticalGradBottom
.ry() += fontMetrics
.height() + 5;
122 QLinearGradient
gradient(start
, verticalGradBottom
);
123 gradient
.setColorAt(0, outlineColor
);
124 gradient
.setColorAt(1, Qt::transparent
);
125 painter
->fillRect(QRect(start
, QSize(1, fontMetrics
.height() + 5)), gradient
);
127 //END: left vertical line
129 //BEGIN: horizontal line
131 QPoint
start(optRect
.topLeft());
133 QPoint
horizontalGradTop(optRect
.topLeft());
134 horizontalGradTop
.rx() += optRect
.width() - 6;
135 painter
->fillRect(QRect(start
, QSize(optRect
.width() - 6, 1)), outlineColor
);
137 //END: horizontal line
139 //BEGIN: top right corner
142 painter
->setPen(outlineColor
);
143 QPointF
topRight(optRect
.topRight());
145 QRectF
arc(topRight
, QSizeF(4, 4));
146 arc
.translate(0.5, 0.5);
147 painter
->drawArc(arc
, 0, 1440);
150 //END: top right corner
152 //BEGIN: right vertical line
154 QPoint
start(optRect
.topRight());
156 QPoint
verticalGradBottom(optRect
.topRight());
157 verticalGradBottom
.ry() += fontMetrics
.height() + 5;
158 QLinearGradient
gradient(start
, verticalGradBottom
);
159 gradient
.setColorAt(0, outlineColor
);
160 gradient
.setColorAt(1, Qt::transparent
);
161 painter
->fillRect(QRect(start
, QSize(1, fontMetrics
.height() + 5)), gradient
);
163 //END: right vertical line
165 const int iconSize
= KIconLoader::global()->currentSize(KIconLoader::Small
);
167 //BEGIN: select/unselect all
169 if (this->category
== category
) {
170 QRect
iconAllRect(option
.rect
);
171 iconAllRect
.setTop(iconAllRect
.top() + 4);
172 iconAllRect
.setLeft(iconAllRect
.right() - 16 - 7);
173 iconAllRect
.setSize(QSize(iconSize
, iconSize
));
174 if (!allCategorySelected(category
)) {
175 if (iconAllRect
.contains(pos
)) {
176 painter
->drawPixmap(iconAllRect
, selectAllHovered
);
178 painter
->drawPixmap(iconAllRect
, selectAll
);
181 painter
->drawPixmap(iconAllRect
, selectAllDisabled
);
183 QRect
iconNoneRect(option
.rect
);
184 iconNoneRect
.setTop(iconNoneRect
.top() + 4);
185 iconNoneRect
.setLeft(iconNoneRect
.right() - 16 * 2 - 7 * 2);
186 iconNoneRect
.setSize(QSize(iconSize
, iconSize
));
187 if (someCategorySelected(category
)) {
188 if (iconNoneRect
.contains(pos
)) {
189 painter
->drawPixmap(iconNoneRect
, unselectAllHovered
);
191 painter
->drawPixmap(iconNoneRect
, unselectAll
);
194 painter
->drawPixmap(iconNoneRect
, unselectAllDisabled
);
198 //END: select/unselect all
200 //BEGIN: category information
204 switch (index
.column()) {
205 case KDirModel::Owner
: {
207 KUser
user(category
);
208 const QString faceIconPath
= user
.faceIconPath();
209 if (faceIconPath
.isEmpty()) {
210 icon
= KIconLoader::global()->loadIcon("user-identity", KIconLoader::NoGroup
, iconSize
);
212 icon
= QPixmap::fromImage(QImage(faceIconPath
).scaledToHeight(iconSize
, Qt::SmoothTransformation
));
216 case KDirModel::Type
: {
218 const KCategorizedSortFilterProxyModel
*proxyModel
= static_cast<const KCategorizedSortFilterProxyModel
*>(index
.model());
219 const DolphinModel
*model
= static_cast<const DolphinModel
*>(proxyModel
->sourceModel());
220 KFileItem item
= model
->itemForIndex(proxyModel
->mapToSource(index
));
221 // This is the only way of getting the icon right. Others will fail on corner
222 // cases like the item representing this group has been set a different icon,
223 // so the group icon drawn is that one particularly. This way assures the drawn
224 // icon is the one of the mimetype of the group itself. (ereslibre)
225 icon
= KIconLoader::global()->loadMimeTypeIcon(item
.mimeTypePtr()->iconName(), KIconLoader::NoGroup
, iconSize
);
233 QRect
iconRect(option
.rect
);
234 iconRect
.setTop(iconRect
.top() + 4);
235 iconRect
.setLeft(iconRect
.left() + 7);
236 iconRect
.setSize(QSize(iconSize
, iconSize
));
238 painter
->drawPixmap(iconRect
, icon
);
243 QRect
textRect(option
.rect
);
244 textRect
.setTop(textRect
.top() + 7);
245 textRect
.setLeft(textRect
.left() + 7 + (paintIcon
? (iconSize
+ 6) : 0));
246 textRect
.setHeight(qMax(fontMetrics
.height(), iconSize
));
247 textRect
.setRight(textRect
.right() - 7);
248 textRect
.setBottom(textRect
.bottom() - 5); // only one pixel separation here (no gradient)
251 painter
->setFont(font
);
252 QColor
penColor(option
.palette
.text().color());
253 penColor
.setAlphaF(0.6);
254 painter
->setPen(penColor
);
255 painter
->drawText(textRect
, Qt::AlignLeft
| Qt::AlignVCenter
, category
);
260 //BEGIN: category information
263 int DolphinCategoryDrawer::categoryHeight(const QModelIndex
&index
, const QStyleOption
&) const
265 int iconSize
= KIconLoader::global()->currentSize(KIconLoader::Small
);
266 QFont
font(QApplication::font());
268 const QFontMetrics fontMetrics
= QFontMetrics(font
);
269 int heightWithoutIcon
= fontMetrics
.height() + (iconSize
/ 4) * 2 + 1; /* 1 pixel-width gradient */
272 switch (index
.column()) {
273 case KDirModel::Owner
:
274 case KDirModel::Type
:
282 return qMax(heightWithoutIcon
+ 5, iconSize
+ 1 /* 1 pixel-width gradient */
283 + 5 /* top and bottom separation */);
286 return heightWithoutIcon
+ 5;
289 void DolphinCategoryDrawer::mouseButtonPressed(const QModelIndex
&index
, const QRect
&blockRect
, QMouseEvent
*event
)
291 if (!index
.isValid()) {
295 const QString category
= index
.model()->data(index
, KCategorizedSortFilterProxyModel::CategoryDisplayRole
).toString();
296 int iconSize
= KIconLoader::global()->currentSize(KIconLoader::Small
);
297 if (this->category
== category
) {
298 QRect
iconAllRect(blockRect
);
299 iconAllRect
.setTop(iconAllRect
.top() + 4);
300 iconAllRect
.setLeft(iconAllRect
.right() - 16 - 7);
301 iconAllRect
.setSize(QSize(iconSize
, iconSize
));
302 if (iconAllRect
.contains(pos
)) {
304 hotSpotPressed
= SelectAllHotSpot
;
305 categoryPressed
= index
;
308 QRect
iconNoneRect(blockRect
);
309 iconNoneRect
.setTop(iconNoneRect
.top() + 4);
310 iconNoneRect
.setLeft(iconNoneRect
.right() - 16 * 2 - 7 * 2);
311 iconNoneRect
.setSize(QSize(iconSize
, iconSize
));
312 if (iconNoneRect
.contains(pos
)) {
314 hotSpotPressed
= UnselectAllHotSpot
;
315 categoryPressed
= index
;
322 void DolphinCategoryDrawer::mouseButtonReleased(const QModelIndex
&index
, const QRect
&blockRect
, QMouseEvent
*event
)
324 if (!index
.isValid() || hotSpotPressed
== NoneHotSpot
|| categoryPressed
!= index
) {
328 categoryPressed
= QModelIndex();
329 const QString category
= index
.model()->data(index
, KCategorizedSortFilterProxyModel::CategoryDisplayRole
).toString();
330 int iconSize
= KIconLoader::global()->currentSize(KIconLoader::Small
);
331 if (this->category
== category
) {
332 QRect
iconAllRect(blockRect
);
333 iconAllRect
.setTop(iconAllRect
.top() + 4);
334 iconAllRect
.setLeft(iconAllRect
.right() - 16 - 7);
335 iconAllRect
.setSize(QSize(iconSize
, iconSize
));
336 if (iconAllRect
.contains(pos
)) {
337 if (hotSpotPressed
== SelectAllHotSpot
) {
339 emit
actionRequested(SelectAll
, index
);
342 hotSpotPressed
= NoneHotSpot
;
346 QRect
iconNoneRect(blockRect
);
347 iconNoneRect
.setTop(iconNoneRect
.top() + 4);
348 iconNoneRect
.setLeft(iconNoneRect
.right() - 16 * 2 - 7 * 2);
349 iconNoneRect
.setSize(QSize(iconSize
, iconSize
));
350 if (iconNoneRect
.contains(pos
)) {
351 if (hotSpotPressed
== UnselectAllHotSpot
) {
353 emit
actionRequested(UnselectAll
, index
);
356 hotSpotPressed
= NoneHotSpot
;
364 void DolphinCategoryDrawer::mouseMoved(const QModelIndex
&index
, const QRect
&, QMouseEvent
*event
)
367 if (!index
.isValid()) {
371 category
= index
.model()->data(index
, KCategorizedSortFilterProxyModel::CategoryDisplayRole
).toString();
374 void DolphinCategoryDrawer::mouseLeft(const QModelIndex
&, const QRect
&)