]> cloud.milkyroute.net Git - dolphin.git/blob - src/kitemviews/kfileitemlistwidget.cpp
Select items when using the rubberband
[dolphin.git] / src / kitemviews / kfileitemlistwidget.cpp
1 /***************************************************************************
2 * Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
18 ***************************************************************************/
19
20 #include "kfileitemlistwidget.h"
21
22 #include "kfileitemmodel.h"
23 #include "kitemlistview.h"
24 #include "kpixmapmodifier_p.h"
25
26 #include <KIcon>
27 #include <KIconEffect>
28 #include <KIconLoader>
29 #include <KLocale>
30 #include <KStringHandler>
31 #include <KDebug>
32
33 #include <QFontMetricsF>
34 #include <QGraphicsSceneResizeEvent>
35 #include <QPainter>
36 #include <QStyleOption>
37 #include <QTextLayout>
38 #include <QTextLine>
39
40 //#define KFILEITEMLISTWIDGET_DEBUG
41
42 KFileItemListWidget::KFileItemListWidget(QGraphicsItem* parent) :
43 KItemListWidget(parent),
44 m_isDir(false),
45 m_dirtyLayout(true),
46 m_dirtyContent(true),
47 m_dirtyContentRoles(),
48 m_layout(IconsLayout),
49 m_pixmapPos(),
50 m_pixmap(),
51 m_scaledPixmapSize(),
52 m_hoverPixmapRect(),
53 m_hoverPixmap(),
54 m_textPos(),
55 m_text(),
56 m_textBoundingRect(),
57 m_sortedVisibleRoles(),
58 m_expansionArea(),
59 m_additionalInfoTextColor()
60 {
61 for (int i = 0; i < TextIdCount; ++i) {
62 m_text[i].setTextFormat(Qt::PlainText);
63 m_text[i].setPerformanceHint(QStaticText::AggressiveCaching);
64 }
65 }
66
67 KFileItemListWidget::~KFileItemListWidget()
68 {
69 }
70
71 void KFileItemListWidget::setLayout(Layout layout)
72 {
73 if (m_layout != layout) {
74 m_layout = layout;
75 m_dirtyLayout = true;
76 update();
77 }
78 }
79
80 KFileItemListWidget::Layout KFileItemListWidget::layout() const
81 {
82 return m_layout;
83 }
84
85 void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
86 {
87 KItemListWidget::paint(painter, option, widget);
88
89 const_cast<KFileItemListWidget*>(this)->updateCache();
90
91 // Draw expansion toggle '>' or 'V'
92 if (m_isDir && !m_expansionArea.isEmpty()) {
93 QStyleOption arrowOption;
94 arrowOption.rect = m_expansionArea.toRect();
95 const QStyle::PrimitiveElement arrow = data()["isExpanded"].toBool()
96 ? QStyle::PE_IndicatorArrowDown : QStyle::PE_IndicatorArrowRight;
97 style()->drawPrimitive(arrow, &arrowOption, painter);
98 }
99
100 const KItemListStyleOption& itemListStyleOption = styleOption();
101 if (isHovered()) {
102 // Blend the unhovered and hovered pixmap if the hovering
103 // animation is ongoing
104 if (hoverOpacity() < 1.0) {
105 drawPixmap(painter, m_pixmap);
106 }
107
108 const qreal opacity = painter->opacity();
109 painter->setOpacity(hoverOpacity() * opacity);
110 drawPixmap(painter, m_hoverPixmap);
111 painter->setOpacity(opacity);
112 } else {
113 drawPixmap(painter, m_pixmap);
114 }
115
116 painter->setFont(itemListStyleOption.font);
117 painter->setPen(itemListStyleOption.palette.text().color());
118 painter->drawStaticText(m_textPos[Name], m_text[Name]);
119
120 painter->setPen(m_additionalInfoTextColor);
121 painter->setFont(itemListStyleOption.font);
122 for (int i = Name + 1; i < TextIdCount; ++i) {
123 painter->drawStaticText(m_textPos[i], m_text[i]);
124 }
125
126 #ifdef KFILEITEMLISTWIDGET_DEBUG
127 painter->setPen(Qt::red);
128 painter->setBrush(Qt::NoBrush);
129 painter->drawText(QPointF(0, itemListStyleOption.fontMetrics.height()), QString::number(index()));
130 painter->drawRect(rect());
131 #endif
132 }
133
134 QRectF KFileItemListWidget::iconBoundingRect() const
135 {
136 const_cast<KFileItemListWidget*>(this)->updateCache();
137
138 QRectF bounds = m_hoverPixmapRect;
139 const qreal margin = styleOption().margin;
140 bounds.adjust(-margin, -margin, margin, margin);
141 return bounds;
142 }
143
144 QRectF KFileItemListWidget::textBoundingRect() const
145 {
146 const_cast<KFileItemListWidget*>(this)->updateCache();
147 return m_textBoundingRect;
148 }
149
150 QRectF KFileItemListWidget::expansionToggleRect() const
151 {
152 const_cast<KFileItemListWidget*>(this)->updateCache();
153 return m_isDir ? m_expansionArea : QRectF();
154 }
155
156 void KFileItemListWidget::dataChanged(const QHash<QByteArray, QVariant>& current,
157 const QSet<QByteArray>& roles)
158 {
159 KItemListWidget::dataChanged(current, roles);
160 m_dirtyContent = true;
161
162 QSet<QByteArray> dirtyRoles;
163 if (roles.isEmpty()) {
164 dirtyRoles = visibleRoles().keys().toSet();
165 dirtyRoles.insert("iconPixmap");
166 dirtyRoles.insert("iconName");
167 } else {
168 dirtyRoles = roles;
169 }
170
171 QSetIterator<QByteArray> it(dirtyRoles);
172 while (it.hasNext()) {
173 const QByteArray& role = it.next();
174 m_dirtyContentRoles.insert(role);
175 }
176 }
177
178 void KFileItemListWidget::visibleRolesChanged(const QHash<QByteArray, int>& current,
179 const QHash<QByteArray, int>& previous)
180 {
181 KItemListWidget::visibleRolesChanged(current, previous);
182 m_dirtyLayout = true;
183
184 // Cache the roles sorted into m_sortedVisibleRoles:
185 const int visibleRolesCount = current.count();
186 m_sortedVisibleRoles.clear();
187 m_sortedVisibleRoles.reserve(visibleRolesCount);
188 for (int i = 0; i < visibleRolesCount; ++i) {
189 m_sortedVisibleRoles.append(QByteArray());
190 }
191
192 QHashIterator<QByteArray, int> it(current);
193 while (it.hasNext()) {
194 it.next();
195
196 const int index = it.value();
197 if (index < 0 || index >= visibleRolesCount || !m_sortedVisibleRoles.at(index).isEmpty()) {
198 kWarning() << "The visible roles have an invalid sort order.";
199 break;
200 }
201
202 const QByteArray& role = it.key();
203 m_sortedVisibleRoles[index] = role;
204 }
205 }
206
207 void KFileItemListWidget::visibleRolesSizesChanged(const QHash<QByteArray, QSizeF>& current,
208 const QHash<QByteArray, QSizeF>& previous)
209 {
210 KItemListWidget::visibleRolesSizesChanged(current, previous);
211 m_dirtyLayout = true;
212 }
213
214 void KFileItemListWidget::styleOptionChanged(const KItemListStyleOption& current,
215 const KItemListStyleOption& previous)
216 {
217 KItemListWidget::styleOptionChanged(current, previous);
218
219 // For the color of the additional info the inactive text color
220 // is not used as this might lead to unreadable text for some color schemes. Instead
221 // the text color is slightly mixed with the background color.
222 const QColor c1 = current.palette.text().color();
223 const QColor c2 = current.palette.background().color();
224 const int p1 = 70;
225 const int p2 = 100 - p1;
226 m_additionalInfoTextColor = QColor((c1.red() * p1 + c2.red() * p2) / 100,
227 (c1.green() * p1 + c2.green() * p2) / 100,
228 (c1.blue() * p1 + c2.blue() * p2) / 100);
229
230 m_dirtyLayout = true;
231 }
232
233 void KFileItemListWidget::hoveredChanged(bool hovered)
234 {
235 Q_UNUSED(hovered);
236 m_dirtyLayout = true;
237 }
238
239 void KFileItemListWidget::resizeEvent(QGraphicsSceneResizeEvent* event)
240 {
241 KItemListWidget::resizeEvent(event);
242 m_dirtyLayout = true;
243 }
244
245 void KFileItemListWidget::updateCache()
246 {
247 if ((!m_dirtyContent && !m_dirtyLayout) || index() < 0) {
248 return;
249 }
250
251 m_isDir = data()["isDir"].toBool();
252
253 updateExpansionArea();
254 updateTextsCache();
255 updatePixmapCache();
256
257 m_dirtyLayout = false;
258 m_dirtyContent = false;
259 m_dirtyContentRoles.clear();
260 }
261
262 void KFileItemListWidget::updateExpansionArea()
263 {
264 if (m_layout == DetailsLayout) {
265 const QHash<QByteArray, QVariant> values = data();
266 Q_ASSERT(values.contains("expansionLevel"));
267 const KItemListStyleOption& option = styleOption();
268 const int expansionLevel = values.value("expansionLevel", 0).toInt();
269
270 const qreal widgetHeight = size().height();
271 const qreal expansionLevelSize = KIconLoader::SizeSmall;
272 const qreal x = option.margin + expansionLevel * widgetHeight;
273 const qreal y = (widgetHeight - expansionLevelSize) / 2;
274 m_expansionArea = QRectF(x, y, expansionLevelSize, expansionLevelSize);
275 } else {
276 m_expansionArea = QRectF();
277 }
278 }
279
280 void KFileItemListWidget::updatePixmapCache()
281 {
282 // Precondition: Requires already updated m_textPos values to calculate
283 // the remaining height when the alignment is vertical.
284
285 const bool iconOnTop = (m_layout == IconsLayout);
286 const KItemListStyleOption& option = styleOption();
287 const int iconHeight = option.iconSize;
288
289 const QHash<QByteArray, QVariant> values = data();
290 const QSizeF widgetSize = size();
291
292 int scaledIconHeight = 0;
293 if (iconOnTop) {
294 scaledIconHeight = static_cast<int>(m_textPos[Name].y() - 3 * option.margin);
295 } else {
296 const int textRowsCount = (m_layout == CompactLayout) ? visibleRoles().count() : 1;
297 const qreal requiredTextHeight = textRowsCount * option.fontMetrics.height();
298 scaledIconHeight = (requiredTextHeight < iconHeight) ? widgetSize.height() - 2 * option.margin : iconHeight;
299 }
300
301 bool updatePixmap = (iconHeight != m_pixmap.height());
302 if (!updatePixmap && m_dirtyContent) {
303 updatePixmap = m_dirtyContentRoles.isEmpty()
304 || m_dirtyContentRoles.contains("iconPixmap")
305 || m_dirtyContentRoles.contains("iconName");
306 }
307
308 if (updatePixmap) {
309 m_pixmap = values["iconPixmap"].value<QPixmap>();
310 if (m_pixmap.isNull()) {
311 // Use the icon that fits to the MIME-type
312 QString iconName = values["iconName"].toString();
313 if (iconName.isEmpty()) {
314 // The icon-name has not been not resolved by KFileItemModelRolesUpdater,
315 // use a generic icon as fallback
316 iconName = QLatin1String("unknown");
317 }
318 m_pixmap = pixmapForIcon(iconName, iconHeight);
319 m_hoverPixmapRect.setSize(m_pixmap.size());
320 } else if (m_pixmap.size() != QSize(iconHeight, iconHeight)) {
321 // A custom pixmap has been applied. Assure that the pixmap
322 // is scaled to the available size.
323 const bool scale = m_pixmap.width() > iconHeight || m_pixmap.height() > iconHeight ||
324 (m_pixmap.width() < iconHeight && m_pixmap.height() < iconHeight);
325 if (scale) {
326 KPixmapModifier::scale(m_pixmap, QSize(iconHeight, iconHeight));
327 }
328 m_hoverPixmapRect.setSize(m_pixmap.size());
329
330 // To simplify the handling of scaling the original pixmap
331 // will be embedded into a square pixmap.
332 QPixmap squarePixmap(iconHeight, iconHeight);
333 squarePixmap.fill(Qt::transparent);
334
335 QPainter painter(&squarePixmap);
336 if (iconOnTop) {
337 const int x = (iconHeight - m_pixmap.width()) / 2; // Center horizontally
338 const int y = iconHeight - m_pixmap.height(); // Align on bottom
339 painter.drawPixmap(x, y, m_pixmap);
340 } else {
341 const int x = iconHeight - m_pixmap.width(); // Align right
342 const int y = (iconHeight - m_pixmap.height()) / 2; // Center vertically
343 painter.drawPixmap(x, y, m_pixmap);
344 }
345
346 m_pixmap = squarePixmap;
347 } else {
348 m_hoverPixmapRect.setSize(m_pixmap.size());
349 }
350
351 Q_ASSERT(m_pixmap.height() == iconHeight);
352 }
353
354 m_scaledPixmapSize = QSize(scaledIconHeight, scaledIconHeight);
355
356 if (iconOnTop) {
357 m_pixmapPos.setX((widgetSize.width() - m_scaledPixmapSize.width()) / 2);
358 } else {
359 m_pixmapPos.setX(m_textPos[Name].x() - 2 * option.margin - scaledIconHeight);
360 }
361 m_pixmapPos.setY(option.margin);
362
363 // Center the hover rectangle horizontally and align it on bottom
364 const qreal x = m_pixmapPos.x() + (m_scaledPixmapSize.width() - m_hoverPixmapRect.width()) / 2.0;
365 const qreal y = m_pixmapPos.y() + m_scaledPixmapSize.height() - m_hoverPixmapRect.height();
366 m_hoverPixmapRect.moveTopLeft(QPointF(x, y));
367
368 // Prepare the pixmap that is used when the item gets hovered
369 if (isHovered()) {
370 m_hoverPixmap = m_pixmap;
371 KIconEffect* effect = KIconLoader::global()->iconEffect();
372 // In the KIconLoader terminology, active = hover.
373 if (effect->hasEffect(KIconLoader::Desktop, KIconLoader::ActiveState)) {
374 m_hoverPixmap = effect->apply(m_pixmap, KIconLoader::Desktop, KIconLoader::ActiveState);
375 } else {
376 m_hoverPixmap = m_pixmap;
377 }
378 } else if (hoverOpacity() <= 0.0) {
379 // No hover animation is ongoing. Clear m_hoverPixmap to save memory.
380 m_hoverPixmap = QPixmap();
381 }
382 }
383
384 void KFileItemListWidget::updateTextsCache()
385 {
386 QTextOption textOption;
387 switch (m_layout) {
388 case IconsLayout:
389 textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
390 textOption.setAlignment(Qt::AlignHCenter);
391 break;
392 case CompactLayout:
393 case DetailsLayout:
394 textOption.setAlignment(Qt::AlignLeft);
395 textOption.setWrapMode(QTextOption::NoWrap);
396 break;
397 default:
398 Q_ASSERT(false);
399 break;
400 }
401
402 for (int i = 0; i < TextIdCount; ++i) {
403 m_text[i].setText(QString());
404 m_text[i].setTextOption(textOption);
405 }
406
407 switch (m_layout) {
408 case IconsLayout: updateIconsLayoutTextCache(); break;
409 case CompactLayout: updateCompactLayoutTextCache(); break;
410 case DetailsLayout: updateDetailsLayoutTextCache(); break;
411 default: Q_ASSERT(false); break;
412 }
413 }
414
415 void KFileItemListWidget::updateIconsLayoutTextCache()
416 {
417 // +------+
418 // | Icon |
419 // +------+
420 //
421 // Name role that
422 // might get wrapped above
423 // several lines.
424 // Additional role 1
425 // Additional role 2
426
427 const QHash<QByteArray, QVariant> values = data();
428
429 const KItemListStyleOption& option = styleOption();
430 const qreal maxWidth = size().width() - 2 * option.margin;
431 const qreal widgetHeight = size().height();
432 const qreal fontHeight = option.fontMetrics.height();
433
434 // Initialize properties for the "name" role. It will be used as anchor
435 // for initializing the position of the other roles.
436 m_text[Name].setText(KStringHandler::preProcessWrap(values["name"].toString()));
437
438 // Calculate the number of lines required for the name and the required width
439 int textLinesCountForName = 0;
440 qreal requiredWidthForName = 0;
441 QTextLine line;
442
443 QTextLayout layout(m_text[Name].text(), option.font);
444 layout.setTextOption(m_text[Name].textOption());
445 layout.beginLayout();
446 while ((line = layout.createLine()).isValid()) {
447 line.setLineWidth(maxWidth);
448 requiredWidthForName = qMax(requiredWidthForName, line.naturalTextWidth());
449 ++textLinesCountForName;
450 }
451 layout.endLayout();
452
453 // Use one line for each additional information
454 int textLinesCount = textLinesCountForName;
455 const int additionalRolesCount = qMax(visibleRoles().count() - 1, 0);
456 textLinesCount += additionalRolesCount;
457
458 m_text[Name].setTextWidth(maxWidth);
459 m_textPos[Name] = QPointF(option.margin, widgetHeight - textLinesCount * fontHeight - option.margin);
460 m_textBoundingRect = QRectF(option.margin + (maxWidth - requiredWidthForName) / 2,
461 m_textPos[Name].y(),
462 requiredWidthForName,
463 m_text[Name].size().height());
464
465 // Calculate the position for each additional information
466 qreal y = m_textPos[Name].y() + textLinesCountForName * fontHeight;
467 foreach (const QByteArray& role, m_sortedVisibleRoles) {
468 const TextId textId = roleTextId(role);
469 if (textId == Name) {
470 continue;
471 }
472
473 const QString text = roleText(textId, values[role]);
474 m_text[textId].setText(text);
475
476 qreal requiredWidth = 0;
477
478 QTextLayout layout(text, option.font);
479 layout.setTextOption(m_text[textId].textOption());
480 layout.beginLayout();
481 QTextLine textLine = layout.createLine();
482 if (textLine.isValid()) {
483 textLine.setLineWidth(maxWidth);
484 requiredWidth = textLine.naturalTextWidth();
485 if (textLine.textLength() < text.length()) {
486 // TODO: QFontMetrics::elidedText() works different regarding the given width
487 // in comparison to QTextLine::setLineWidth(). It might happen that the text does
488 // not get elided although it does not fit into the given width. As workaround
489 // the margin is substracted.
490 const QString elidedText = option.fontMetrics.elidedText(text, Qt::ElideRight, maxWidth - option.margin);
491 m_text[textId].setText(elidedText);
492 }
493 }
494 layout.endLayout();
495
496 m_textPos[textId] = QPointF(option.margin, y);
497 m_text[textId].setTextWidth(maxWidth);
498
499 const QRectF textBoundingRect(option.margin + (maxWidth - requiredWidth) / 2, y, requiredWidth, fontHeight);
500 m_textBoundingRect |= textBoundingRect;
501
502 y += fontHeight;
503 }
504
505 // Add a margin to the text bounding rectangle
506 const qreal margin = option.margin;
507 m_textBoundingRect.adjust(-margin, -margin, margin, margin);
508 }
509
510 void KFileItemListWidget::updateCompactLayoutTextCache()
511 {
512 // +------+ Name role
513 // | Icon | Additional role 1
514 // +------+ Additional role 2
515
516 const QHash<QByteArray, QVariant> values = data();
517
518 const KItemListStyleOption& option = styleOption();
519 const qreal widgetHeight = size().height();
520 const qreal fontHeight = option.fontMetrics.height();
521 const qreal textLinesHeight = qMax(visibleRoles().count(), 1) * fontHeight;
522 const int scaledIconSize = (textLinesHeight < option.iconSize) ? widgetHeight - 2 * option.margin : option.iconSize;
523
524 qreal maximumRequiredTextWidth = 0;
525 const qreal x = option.margin * 3 + scaledIconSize;
526 qreal y = (widgetHeight - textLinesHeight) / 2;
527 const qreal maxWidth = size().width() - x - option.margin;
528 foreach (const QByteArray& role, m_sortedVisibleRoles) {
529 const TextId textId = roleTextId(role);
530
531 const QString text = roleText(textId, values[role]);
532 m_text[textId].setText(text);
533
534 qreal requiredWidth = option.fontMetrics.width(text);
535 if (requiredWidth > maxWidth) {
536 requiredWidth = maxWidth;
537 const QString elidedText = option.fontMetrics.elidedText(text, Qt::ElideRight, maxWidth);
538 m_text[textId].setText(elidedText);
539 }
540
541 m_textPos[textId] = QPointF(x, y);
542 m_text[textId].setTextWidth(maxWidth);
543
544 maximumRequiredTextWidth = qMax(maximumRequiredTextWidth, requiredWidth);
545
546 y += fontHeight;
547 }
548
549 m_textBoundingRect = QRectF(x - option.margin, 0, maximumRequiredTextWidth + 2 * option.margin, widgetHeight);
550 }
551
552 void KFileItemListWidget::updateDetailsLayoutTextCache()
553 {
554 // Precondition: Requires already updated m_expansionArea
555 // to determine the left position.
556
557 // +------+
558 // | Icon | Name role Additional role 1 Additional role 2
559 // +------+
560 m_textBoundingRect = QRectF();
561
562 const KItemListStyleOption& option = styleOption();
563 const QHash<QByteArray, QVariant> values = data();
564
565 const qreal widgetHeight = size().height();
566 const int scaledIconSize = widgetHeight - 2 * option.margin;
567 const int fontHeight = option.fontMetrics.height();
568
569 qreal x = m_expansionArea.right() + option.margin * 3 + scaledIconSize;
570 const qreal y = qMax(qreal(option.margin), (widgetHeight - fontHeight) / 2);
571
572 foreach (const QByteArray& role, m_sortedVisibleRoles) {
573 const TextId textId = roleTextId(role);
574
575 const QString text = roleText(textId, values[role]);
576 m_text[textId].setText(text);
577
578 const qreal requiredWidth = option.fontMetrics.width(text);
579 m_textPos[textId] = QPointF(x, y);
580
581 const qreal columnWidth = visibleRolesSizes().value(role, QSizeF(0, 0)).width();
582 x += columnWidth;
583
584 switch (textId) {
585 case Name: {
586 m_textBoundingRect = QRectF(m_textPos[textId].x() - option.margin, 0,
587 requiredWidth + 2 * option.margin, size().height());
588
589 // The column after the name should always be aligned on the same x-position independent
590 // from the expansion-level shown in the name column
591 x -= m_expansionArea.right();
592 break;
593 }
594 case Size:
595 // The values for the size should be right aligned
596 m_textPos[textId].rx() += columnWidth - requiredWidth - 2 * option.margin;
597 break;
598
599 default:
600 break;
601 }
602 }
603 }
604
605 QString KFileItemListWidget::roleText(TextId textId, const QVariant& roleValue) const
606 {
607 QString text;
608
609 switch (textId) {
610 case Name:
611 case Permissions:
612 case Owner:
613 case Group:
614 case Type:
615 case Destination:
616 case Path:
617 text = roleValue.toString();
618 break;
619
620 case Size: {
621 if (data().value("isDir").toBool()) {
622 // The item represents a directory. Show the number of sub directories
623 // instead of the file size of the directory.
624 if (!roleValue.isNull()) {
625 const KIO::filesize_t size = roleValue.value<KIO::filesize_t>();
626 text = i18ncp("@item:intable", "%1 item", "%1 items", size);
627 }
628 } else {
629 const KIO::filesize_t size = roleValue.value<KIO::filesize_t>();
630 text = KIO::convertSize(size);
631 }
632 break;
633 }
634
635 case Date: {
636 const QDateTime dateTime = roleValue.toDateTime();
637 text = KGlobal::locale()->formatDateTime(dateTime);
638 break;
639 }
640
641 default:
642 Q_ASSERT(false);
643 break;
644 }
645
646 return text;
647 }
648
649 void KFileItemListWidget::drawPixmap(QPainter* painter, const QPixmap& pixmap)
650 {
651 const bool isHiddenItem = m_text[Name].text().startsWith(QLatin1Char('.'));
652 qreal opacity;
653 if (isHiddenItem) {
654 opacity = painter->opacity();
655 painter->setOpacity(opacity * 0.3);
656 }
657
658 if (m_scaledPixmapSize != pixmap.size()) {
659 QPixmap scaledPixmap = pixmap;
660 KPixmapModifier::scale(scaledPixmap, m_scaledPixmapSize);
661 painter->drawPixmap(m_pixmapPos, scaledPixmap);
662
663 #ifdef KFILEITEMLISTWIDGET_DEBUG
664 painter->setPen(Qt::green);
665 painter->drawRect(QRectF(m_pixmapPos, QSizeF(scaledPixmap.size())));
666 #endif
667 } else {
668 painter->drawPixmap(m_pixmapPos, pixmap);
669 }
670
671 if (isHiddenItem) {
672 painter->setOpacity(opacity);
673 }
674 }
675
676 QPixmap KFileItemListWidget::pixmapForIcon(const QString& name, int size)
677 {
678 const KIcon icon(name);
679
680 int requestedSize;
681 if (size <= KIconLoader::SizeSmall) {
682 requestedSize = KIconLoader::SizeSmall;
683 } else if (size <= KIconLoader::SizeSmallMedium) {
684 requestedSize = KIconLoader::SizeSmallMedium;
685 } else if (size <= KIconLoader::SizeMedium) {
686 requestedSize = KIconLoader::SizeMedium;
687 } else if (size <= KIconLoader::SizeLarge) {
688 requestedSize = KIconLoader::SizeLarge;
689 } else if (size <= KIconLoader::SizeHuge) {
690 requestedSize = KIconLoader::SizeHuge;
691 } else if (size <= KIconLoader::SizeEnormous) {
692 requestedSize = KIconLoader::SizeEnormous;
693 } else if (size <= KIconLoader::SizeEnormous * 2) {
694 requestedSize = KIconLoader::SizeEnormous * 2;
695 } else {
696 requestedSize = size;
697 }
698
699 QPixmap pixmap = icon.pixmap(requestedSize, requestedSize);
700 if (requestedSize != size) {
701 KPixmapModifier::scale(pixmap, QSize(size, size));
702 }
703
704 return pixmap;
705 }
706
707 KFileItemListWidget::TextId KFileItemListWidget::roleTextId(const QByteArray& role)
708 {
709 static QHash<QByteArray, TextId> rolesHash;
710 if (rolesHash.isEmpty()) {
711 rolesHash.insert("name", Name);
712 rolesHash.insert("size", Size);
713 rolesHash.insert("date", Date);
714 rolesHash.insert("permissions", Permissions);
715 rolesHash.insert("owner", Owner);
716 rolesHash.insert("group", Group);
717 rolesHash.insert("type", Type);
718 rolesHash.insert("destination", Destination);
719 rolesHash.insert("path", Path);
720 }
721
722 return rolesHash.value(role);
723 }
724
725 #include "kfileitemlistwidget.moc"