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>
35 #include <KIconLoader>
36 #include <KIconEffect>
37 #include <KCategorizedSortFilterProxyModel>
39 #include <KCategorizedView>
41 #include "dolphinview.h"
42 #include "dolphinmodel.h"
44 #define HORIZONTAL_HINT 3
46 DolphinCategoryDrawer::DolphinCategoryDrawer(KCategorizedView
*view
)
47 : KCategoryDrawerV3(view
)
48 , hotSpotPressed(NoneHotSpot
)
49 , selectAll(KIconLoader::global()->loadIcon("list-add", KIconLoader::Desktop
, 16))
50 , selectAllHovered(KIconLoader::global()->iconEffect()->apply(selectAll
, KIconLoader::Desktop
, KIconLoader::ActiveState
))
51 , selectAllDisabled(KIconLoader::global()->iconEffect()->apply(selectAll
, KIconLoader::Desktop
, KIconLoader::DisabledState
))
52 , unselectAll(KIconLoader::global()->loadIcon("list-remove", KIconLoader::Desktop
, 16))
53 , unselectAllHovered(KIconLoader::global()->iconEffect()->apply(unselectAll
, KIconLoader::Desktop
, KIconLoader::ActiveState
))
54 , unselectAllDisabled(KIconLoader::global()->iconEffect()->apply(unselectAll
, KIconLoader::Desktop
, KIconLoader::DisabledState
))
58 DolphinCategoryDrawer::~DolphinCategoryDrawer()
62 bool DolphinCategoryDrawer::allCategorySelected(const QString
&category
) const
64 const QModelIndexList list
= view()->block(category
);
65 foreach (const QModelIndex
&index
, list
) {
66 if (!view()->selectionModel()->isSelected(index
)) {
73 bool DolphinCategoryDrawer::someCategorySelected(const QString
&category
) const
75 const QModelIndexList list
= view()->block(category
);
76 foreach (const QModelIndex
&index
, list
) {
77 if (view()->selectionModel()->isSelected(index
)) {
84 void DolphinCategoryDrawer::drawCategory(const QModelIndex
&index
, int sortRole
,
85 const QStyleOption
&option
, QPainter
*painter
) const
88 painter
->setRenderHint(QPainter::Antialiasing
);
90 if (!index
.isValid()) {
94 const QString category
= index
.model()->data(index
, KCategorizedSortFilterProxyModel::CategoryDisplayRole
).toString();
95 const QRect optRect
= option
.rect
;
96 QFont
font(QApplication::font());
98 const QFontMetrics fontMetrics
= QFontMetrics(font
);
100 QColor outlineColor
= option
.palette
.text().color();
101 outlineColor
.setAlphaF(0.35);
103 //BEGIN: top left corner
106 painter
->setPen(outlineColor
);
107 const QPointF
topLeft(optRect
.topLeft());
108 QRectF
arc(topLeft
, QSizeF(4, 4));
109 arc
.translate(0.5, 0.5);
110 painter
->drawArc(arc
, 1440, 1440);
113 //END: top left corner
115 //BEGIN: left vertical line
117 QPoint
start(optRect
.topLeft());
119 QPoint
verticalGradBottom(optRect
.topLeft());
120 verticalGradBottom
.ry() += fontMetrics
.height() + 5;
121 QLinearGradient
gradient(start
, verticalGradBottom
);
122 gradient
.setColorAt(0, outlineColor
);
123 gradient
.setColorAt(1, Qt::transparent
);
124 painter
->fillRect(QRect(start
, QSize(1, fontMetrics
.height() + 5)), gradient
);
126 //END: left vertical line
128 //BEGIN: horizontal line
130 QPoint
start(optRect
.topLeft());
132 QPoint
horizontalGradTop(optRect
.topLeft());
133 horizontalGradTop
.rx() += optRect
.width() - 6;
134 painter
->fillRect(QRect(start
, QSize(optRect
.width() - 6, 1)), outlineColor
);
136 //END: horizontal line
138 //BEGIN: top right corner
141 painter
->setPen(outlineColor
);
142 QPointF
topRight(optRect
.topRight());
144 QRectF
arc(topRight
, QSizeF(4, 4));
145 arc
.translate(0.5, 0.5);
146 painter
->drawArc(arc
, 0, 1440);
149 //END: top right corner
151 //BEGIN: right vertical line
153 QPoint
start(optRect
.topRight());
155 QPoint
verticalGradBottom(optRect
.topRight());
156 verticalGradBottom
.ry() += fontMetrics
.height() + 5;
157 QLinearGradient
gradient(start
, verticalGradBottom
);
158 gradient
.setColorAt(0, outlineColor
);
159 gradient
.setColorAt(1, Qt::transparent
);
160 painter
->fillRect(QRect(start
, QSize(1, fontMetrics
.height() + 5)), gradient
);
162 //END: right vertical line
164 const int iconSize
= KIconLoader::global()->currentSize(KIconLoader::Small
);
166 //BEGIN: select/unselect all
168 if (this->category
== category
) {
169 QRect
iconAllRect(option
.rect
);
170 iconAllRect
.setTop(iconAllRect
.top() + 4);
171 iconAllRect
.setLeft(iconAllRect
.right() - 16 - 7);
172 iconAllRect
.setSize(QSize(iconSize
, iconSize
));
173 if (!allCategorySelected(category
)) {
174 if (iconAllRect
.contains(pos
)) {
175 painter
->drawPixmap(iconAllRect
, selectAllHovered
);
177 painter
->drawPixmap(iconAllRect
, selectAll
);
180 painter
->drawPixmap(iconAllRect
, selectAllDisabled
);
182 QRect
iconNoneRect(option
.rect
);
183 iconNoneRect
.setTop(iconNoneRect
.top() + 4);
184 iconNoneRect
.setLeft(iconNoneRect
.right() - 16 * 2 - 7 * 2);
185 iconNoneRect
.setSize(QSize(iconSize
, iconSize
));
186 if (someCategorySelected(category
)) {
187 if (iconNoneRect
.contains(pos
)) {
188 painter
->drawPixmap(iconNoneRect
, unselectAllHovered
);
190 painter
->drawPixmap(iconNoneRect
, unselectAll
);
193 painter
->drawPixmap(iconNoneRect
, unselectAllDisabled
);
197 //END: select/unselect all
199 //BEGIN: category information
203 switch (index
.column()) {
204 case KDirModel::Owner
: {
206 KUser
user(category
);
207 const QString faceIconPath
= user
.faceIconPath();
208 if (faceIconPath
.isEmpty()) {
209 icon
= KIconLoader::global()->loadIcon("user-identity", KIconLoader::NoGroup
, iconSize
);
211 icon
= QPixmap::fromImage(QImage(faceIconPath
).scaledToHeight(iconSize
, Qt::SmoothTransformation
));
215 case KDirModel::Type
: {
217 const KCategorizedSortFilterProxyModel
*proxyModel
= static_cast<const KCategorizedSortFilterProxyModel
*>(index
.model());
218 const DolphinModel
*model
= static_cast<const DolphinModel
*>(proxyModel
->sourceModel());
219 KFileItem item
= model
->itemForIndex(proxyModel
->mapToSource(index
));
220 // This is the only way of getting the icon right. Others will fail on corner
221 // cases like the item representing this group has been set a different icon,
222 // so the group icon drawn is that one particularly. This way assures the drawn
223 // icon is the one of the mimetype of the group itself. (ereslibre)
224 icon
= KIconLoader::global()->loadMimeTypeIcon(item
.mimeTypePtr()->iconName(), KIconLoader::NoGroup
, iconSize
);
232 QRect
iconRect(option
.rect
);
233 iconRect
.setTop(iconRect
.top() + 4);
234 iconRect
.setLeft(iconRect
.left() + 7);
235 iconRect
.setSize(QSize(iconSize
, iconSize
));
237 painter
->drawPixmap(iconRect
, icon
);
242 QRect
textRect(option
.rect
);
243 textRect
.setTop(textRect
.top() + 7);
244 textRect
.setLeft(textRect
.left() + 7 + (paintIcon
? (iconSize
+ 6) : 0));
245 textRect
.setHeight(qMax(fontMetrics
.height(), iconSize
));
246 textRect
.setRight(textRect
.right() - 7);
247 textRect
.setBottom(textRect
.bottom() - 5); // only one pixel separation here (no gradient)
250 painter
->setFont(font
);
251 QColor
penColor(option
.palette
.text().color());
252 penColor
.setAlphaF(0.6);
253 painter
->setPen(penColor
);
254 painter
->drawText(textRect
, Qt::AlignLeft
| Qt::AlignVCenter
, category
);
259 //BEGIN: category information
262 int DolphinCategoryDrawer::categoryHeight(const QModelIndex
&index
, const QStyleOption
&) const
264 int iconSize
= KIconLoader::global()->currentSize(KIconLoader::Small
);
265 QFont
font(QApplication::font());
267 const QFontMetrics fontMetrics
= QFontMetrics(font
);
268 int heightWithoutIcon
= fontMetrics
.height() + (iconSize
/ 4) * 2 + 1; /* 1 pixel-width gradient */
271 switch (index
.column()) {
272 case KDirModel::Owner
:
273 case KDirModel::Type
:
281 return qMax(heightWithoutIcon
+ 5, iconSize
+ 1 /* 1 pixel-width gradient */
282 + 5 /* top and bottom separation */);
285 return heightWithoutIcon
+ 5;
288 void DolphinCategoryDrawer::mouseButtonPressed(const QModelIndex
&index
, const QRect
&blockRect
, QMouseEvent
*event
)
290 if (!index
.isValid()) {
294 const QString category
= index
.model()->data(index
, KCategorizedSortFilterProxyModel::CategoryDisplayRole
).toString();
295 int iconSize
= KIconLoader::global()->currentSize(KIconLoader::Small
);
296 if (this->category
== category
) {
297 QRect
iconAllRect(blockRect
);
298 iconAllRect
.setTop(iconAllRect
.top() + 4);
299 iconAllRect
.setLeft(iconAllRect
.right() - 16 - 7);
300 iconAllRect
.setSize(QSize(iconSize
, iconSize
));
301 if (iconAllRect
.contains(pos
)) {
303 hotSpotPressed
= SelectAllHotSpot
;
304 categoryPressed
= index
;
307 QRect
iconNoneRect(blockRect
);
308 iconNoneRect
.setTop(iconNoneRect
.top() + 4);
309 iconNoneRect
.setLeft(iconNoneRect
.right() - 16 * 2 - 7 * 2);
310 iconNoneRect
.setSize(QSize(iconSize
, iconSize
));
311 if (iconNoneRect
.contains(pos
)) {
313 hotSpotPressed
= UnselectAllHotSpot
;
314 categoryPressed
= index
;
321 void DolphinCategoryDrawer::mouseButtonReleased(const QModelIndex
&index
, const QRect
&blockRect
, QMouseEvent
*event
)
323 if (!index
.isValid() || hotSpotPressed
== NoneHotSpot
|| categoryPressed
!= index
) {
327 categoryPressed
= QModelIndex();
328 const QString category
= index
.model()->data(index
, KCategorizedSortFilterProxyModel::CategoryDisplayRole
).toString();
329 int iconSize
= KIconLoader::global()->currentSize(KIconLoader::Small
);
330 if (this->category
== category
) {
331 QRect
iconAllRect(blockRect
);
332 iconAllRect
.setTop(iconAllRect
.top() + 4);
333 iconAllRect
.setLeft(iconAllRect
.right() - 16 - 7);
334 iconAllRect
.setSize(QSize(iconSize
, iconSize
));
335 if (iconAllRect
.contains(pos
)) {
336 if (hotSpotPressed
== SelectAllHotSpot
) {
338 emit
actionRequested(SelectAll
, index
);
341 hotSpotPressed
= NoneHotSpot
;
345 QRect
iconNoneRect(blockRect
);
346 iconNoneRect
.setTop(iconNoneRect
.top() + 4);
347 iconNoneRect
.setLeft(iconNoneRect
.right() - 16 * 2 - 7 * 2);
348 iconNoneRect
.setSize(QSize(iconSize
, iconSize
));
349 if (iconNoneRect
.contains(pos
)) {
350 if (hotSpotPressed
== UnselectAllHotSpot
) {
352 emit
actionRequested(UnselectAll
, index
);
355 hotSpotPressed
= NoneHotSpot
;
363 void DolphinCategoryDrawer::mouseMoved(const QModelIndex
&index
, const QRect
&, QMouseEvent
*event
)
366 if (!index
.isValid()) {
370 category
= index
.model()->data(index
, KCategorizedSortFilterProxyModel::CategoryDisplayRole
).toString();
373 void DolphinCategoryDrawer::mouseLeft(const QModelIndex
&, const QRect
&)