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