28#include <QApplication>
34#include <QPainterPath>
37#include <QPaintEngine>
54#if defined(Q_WS_X11) && defined(HAVE_XRENDER)
56# include <X11/extensions/Xrender.h>
65 int left, right, top, bottom;
69class KFileItemDelegate::Private
72 enum MarginType { ItemMargin = 0, TextMargin, IconMargin, NMargins };
77 QSize decorationSizeHint(
const QStyleOptionViewItemV4 &option,
const QModelIndex &index)
const;
78 QSize displaySizeHint(
const QStyleOptionViewItemV4 &option,
const QModelIndex &index)
const;
79 QString replaceNewlines(
const QString &
string)
const;
80 inline KFileItem fileItem(
const QModelIndex &index)
const;
81 QString elidedText(QTextLayout &layout,
const QStyleOptionViewItemV4 &option,
const QSize &maxSize)
const;
82 QSize layoutText(QTextLayout &layout,
const QStyleOptionViewItemV4 &option,
83 const QString &text,
const QSize &constraints)
const;
84 QSize layoutText(QTextLayout &layout,
const QString &text,
int maxWidth)
const;
85 inline void setLayoutOptions(QTextLayout &layout,
const QStyleOptionViewItemV4 &options)
const;
86 inline bool verticalLayout(
const QStyleOptionViewItemV4 &option)
const;
87 inline QBrush brush(
const QVariant &value,
const QStyleOptionViewItemV4 &option)
const;
88 QBrush foregroundBrush(
const QStyleOptionViewItemV4 &option,
const QModelIndex &index)
const;
89 inline void setActiveMargins(Qt::Orientation layout);
90 void setVerticalMargin(MarginType type,
int left,
int right,
int top,
int bottom);
91 void setHorizontalMargin(MarginType type,
int left,
int right,
int top,
int bottom);
92 inline void setVerticalMargin(MarginType type,
int hor,
int ver);
93 inline void setHorizontalMargin(MarginType type,
int hor,
int ver);
94 inline QRect addMargin(
const QRect &rect, MarginType type)
const;
95 inline QRect subtractMargin(
const QRect &rect, MarginType type)
const;
96 inline QSize addMargin(
const QSize &size, MarginType type)
const;
97 inline QSize subtractMargin(
const QSize &size, MarginType type)
const;
98 QString itemSize(
const QModelIndex &index,
const KFileItem &item)
const;
99 QString
information(
const QStyleOptionViewItemV4 &option,
const QModelIndex &index,
const KFileItem &item)
const;
100 bool isListView(
const QStyleOptionViewItemV4 &option)
const;
101 QString display(
const QModelIndex &index)
const;
102 QIcon decoration(
const QStyleOptionViewItemV4 &option,
const QModelIndex &index)
const;
103 QPoint iconPosition(
const QStyleOptionViewItemV4 &option)
const;
104 QRect labelRectangle(
const QStyleOptionViewItemV4 &option)
const;
105 void layoutTextItems(
const QStyleOptionViewItemV4 &option,
const QModelIndex &index,
106 QTextLayout *labelLayout, QTextLayout *infoLayout, QRect *textBoundingRect)
const;
107 void drawTextItems(QPainter *painter,
const QTextLayout &labelLayout,
const QTextLayout &infoLayout,
108 const QRect &textBoundingRect)
const;
109 KIO::AnimationState *animationState(
const QStyleOptionViewItemV4 &option,
const QModelIndex &index,
110 const QAbstractItemView *view)
const;
112 QPixmap applyHoverEffect(
const QPixmap &icon)
const;
113 QPixmap transition(
const QPixmap &from,
const QPixmap &to, qreal amount)
const;
114 void initStyleOption(QStyleOptionViewItemV4 *option,
const QModelIndex &index)
const;
115 void drawFocusRect(QPainter *painter,
const QStyleOptionViewItemV4 &option,
const QRect &rect)
const;
117 void gotNewIcon(
const QModelIndex& index);
119 void paintJobTransfers(QPainter* painter,
const qreal& jobAnimationAngle,
const QPoint& iconPos,
const QStyleOptionViewItemV4& opt);
124 QPointF shadowOffset;
127 bool showToolTipWhenElided;
128 QTextOption::WrapMode wrapMode;
129 bool jobTransfersVisible;
135 Margin verticalMargin[NMargins];
136 Margin horizontalMargin[NMargins];
137 Margin *activeMargins;
142 : shadowColor(Qt::transparent), shadowOffset(1, 1), shadowBlur(2), maximumSize(0, 0),
143 showToolTipWhenElided(true), wrapMode( QTextOption::WrapAtWordBoundaryOrAnywhere ), jobTransfersVisible(false),
144 q(parent), animationHandler(new
KIO::DelegateAnimationHandler(parent)), activeMargins(0)
149void KFileItemDelegate::Private::setActiveMargins(Qt::Orientation layout)
151 activeMargins = (layout == Qt::Horizontal ?
152 horizontalMargin : verticalMargin);
156void KFileItemDelegate::Private::setVerticalMargin(MarginType type,
int left,
int top,
int right,
int bottom)
158 verticalMargin[type].left = left;
159 verticalMargin[type].right = right;
160 verticalMargin[type].top = top;
161 verticalMargin[type].bottom = bottom;
165void KFileItemDelegate::Private::setHorizontalMargin(MarginType type,
int left,
int top,
int right,
int bottom)
167 horizontalMargin[type].left = left;
168 horizontalMargin[type].right = right;
169 horizontalMargin[type].top = top;
170 horizontalMargin[type].bottom = bottom;
174void KFileItemDelegate::Private::setVerticalMargin(MarginType type,
int horizontal,
int vertical)
176 setVerticalMargin(type, horizontal, vertical, horizontal, vertical);
180void KFileItemDelegate::Private::setHorizontalMargin(MarginType type,
int horizontal,
int vertical)
182 setHorizontalMargin(type, horizontal, vertical, horizontal, vertical);
186QRect KFileItemDelegate::Private::addMargin(
const QRect &rect, MarginType type)
const
188 Q_ASSERT(activeMargins != 0);
189 const Margin &m = activeMargins[type];
190 return rect.adjusted(-m.left, -m.top, m.right, m.bottom);
194QRect KFileItemDelegate::Private::subtractMargin(
const QRect &rect, MarginType type)
const
196 Q_ASSERT(activeMargins != 0);
197 const Margin &m = activeMargins[type];
198 return rect.adjusted(m.left, m.top, -m.right, -m.bottom);
202QSize KFileItemDelegate::Private::addMargin(
const QSize &size, MarginType type)
const
204 Q_ASSERT(activeMargins != 0);
205 const Margin &m = activeMargins[type];
206 return QSize(size.width() + m.left + m.right, size.height() + m.top + m.bottom);
210QSize KFileItemDelegate::Private::subtractMargin(
const QSize &size, MarginType type)
const
212 Q_ASSERT(activeMargins != 0);
213 const Margin &m = activeMargins[type];
214 return QSize(size.width() - m.left - m.right, size.height() - m.top - m.bottom);
219QString KFileItemDelegate::Private::itemSize(
const QModelIndex &index,
const KFileItem &item)
const
236 return i18ncp(
"Items in a folder",
"1 item",
"%1 items", count);
241QString KFileItemDelegate::Private::information(
const QStyleOptionViewItemV4 &option,
const QModelIndex &index,
246 if (informationList.isEmpty() || item.
isNull() || !isListView(option))
254 if (!
string.isEmpty())
255 string += QChar::LineSeparator;
260 string += itemSize(index, item);
268 string += QString(
'0') + QString::number(item.
permissions(), 8);
272 string += item.
user();
276 string += item.
user() +
':' + item.
group();
324KFileItem KFileItemDelegate::Private::fileItem(
const QModelIndex &index)
const
327 return qvariant_cast<KFileItem>(value);
332QString KFileItemDelegate::Private::replaceNewlines(
const QString &text)
const
334 QString
string = text;
335 const QChar newline = QLatin1Char(
'\n');
337 for (
int i = 0; i <
string.length(); i++)
338 if (
string[i] == newline)
339 string[i] = QChar::LineSeparator;
346QSize KFileItemDelegate::Private::layoutText(QTextLayout &layout,
const QStyleOptionViewItemV4 &option,
347 const QString &text,
const QSize &constraints)
const
349 const QSize size = layoutText(layout, text, constraints.width());
351 if (size.width() > constraints.width() || size.height() > constraints.height())
353 const QString elided = elidedText(layout, option, constraints);
354 return layoutText(layout, elided, constraints.width());
362QSize KFileItemDelegate::Private::layoutText(QTextLayout &layout,
const QString &text,
int maxWidth)
const
364 QFontMetrics metrics(layout.font());
365 int leading = metrics.leading();
370 layout.setText(text);
372 layout.beginLayout();
373 while ((line = layout.createLine()).isValid())
375 line.setLineWidth(maxWidth);
377 line.setPosition(QPoint(0, height));
378 height += int(line.height());
379 widthUsed = qMax(widthUsed, line.naturalTextWidth());
383 return QSize(qCeil(widthUsed), height);
391QString KFileItemDelegate::Private::elidedText(QTextLayout &layout,
const QStyleOptionViewItemV4 &option,
392 const QSize &size)
const
394 const QString text = layout.text();
395 int maxWidth = size.width();
396 int maxHeight = size.height();
398 bool wrapText = (option.features & QStyleOptionViewItemV2::WrapText);
401 if (!wrapText && text.indexOf(QChar::LineSeparator) == -1)
402 return option.fontMetrics.elidedText(text, option.textElideMode, maxWidth);
406 elided.reserve(text.length());
408 for (
int i = 0; i < layout.lineCount(); i++)
410 QTextLine line = layout.lineAt(i);
411 int start = line.textStart();
412 int length = line.textLength();
414 height += option.fontMetrics.leading();
415 if (height + line.height() + option.fontMetrics.lineSpacing() > maxHeight)
419 if (line.naturalTextWidth() < maxWidth && text[start + length - 1] == QChar::LineSeparator)
420 elided += text.mid(start, length - 1);
422 elided += option.fontMetrics.elidedText(text.mid(start), option.textElideMode, maxWidth);
425 else if (line.naturalTextWidth() > maxWidth)
427 elided += option.fontMetrics.elidedText(text.mid(start, length), option.textElideMode, maxWidth);
428 if (!elided.endsWith(QChar::LineSeparator))
429 elided += QChar::LineSeparator;
432 elided += text.mid(start, length);
434 height += line.height();
441void KFileItemDelegate::Private::setLayoutOptions(QTextLayout &layout,
const QStyleOptionViewItemV4 &option)
const
443 QTextOption textoption;
444 textoption.setTextDirection(option.direction);
445 textoption.setAlignment(QStyle::visualAlignment(option.direction, option.displayAlignment));
446 textoption.setWrapMode((option.features & QStyleOptionViewItemV2::WrapText) ? wrapMode : QTextOption::NoWrap);
448 layout.setFont(option.font);
449 layout.setTextOption(textoption);
453QSize KFileItemDelegate::Private::displaySizeHint(
const QStyleOptionViewItemV4 &option,
454 const QModelIndex &index)
const
456 QString
label = option.text;
458 if (maximumSize.isEmpty()) {
459 maxWidth = verticalLayout(option) && (option.features & QStyleOptionViewItemV2::WrapText)
460 ? option.decorationSize.width() + 10 : 32757;
463 const Margin &itemMargin = activeMargins[ItemMargin];
464 const Margin &textMargin = activeMargins[TextMargin];
465 maxWidth = maximumSize.width() -
466 (itemMargin.left + itemMargin.right) -
467 (textMargin.left + textMargin.right);
474 const QString info = information(option, index, item);
476 label += QString(QChar::LineSeparator) + info;
479 setLayoutOptions(layout, option);
481 QSize size = layoutText(layout, label, maxWidth);
488 size.setWidth(maxWidth);
491 return addMargin(size, TextMargin);
495QSize KFileItemDelegate::Private::decorationSizeHint(
const QStyleOptionViewItemV4 &option,
496 const QModelIndex &index)
const
500 QSize iconSize = option.icon.actualSize(option.decorationSize);
501 if (!verticalLayout(option))
502 iconSize.rwidth() = option.decorationSize.width();
503 else if (iconSize.width() < option.decorationSize.width())
504 iconSize.rwidth() = qMin(iconSize.width() + 10, option.decorationSize.width());
505 if (iconSize.height() < option.decorationSize.height())
506 iconSize.rheight() = option.decorationSize.height();
508 return addMargin(iconSize, IconMargin);
512bool KFileItemDelegate::Private::verticalLayout(
const QStyleOptionViewItemV4 &option)
const
514 return (option.decorationPosition == QStyleOptionViewItem::Top ||
515 option.decorationPosition == QStyleOptionViewItem::Bottom);
520QBrush KFileItemDelegate::Private::brush(
const QVariant &value,
const QStyleOptionViewItemV4 &option)
const
522 if (value.userType() == qMetaTypeId<KStatefulBrush>())
523 return qvariant_cast<KStatefulBrush>(value).brush(option.palette);
524 switch (value.type())
526 case QVariant::Color:
527 return QBrush(qvariant_cast<QColor>(value));
529 case QVariant::Brush:
530 return qvariant_cast<QBrush>(value);
533 return QBrush(Qt::NoBrush);
538QBrush KFileItemDelegate::Private::foregroundBrush(
const QStyleOptionViewItemV4 &option,
const QModelIndex &index)
const
540 QPalette::ColorGroup cg = QPalette::Active;
541 if (!(option.state & QStyle::State_Enabled)) {
542 cg = QPalette::Disabled;
543 }
else if (!(option.state & QStyle::State_Active)) {
544 cg = QPalette::Inactive;
548 if (option.state & QStyle::State_Selected)
549 return option.palette.brush(cg, QPalette::HighlightedText);
552 const QVariant value = index.data(Qt::ForegroundRole);
554 return brush(value, option);
556 return option.palette.brush(cg, QPalette::Text);
560bool KFileItemDelegate::Private::isListView(
const QStyleOptionViewItemV4 &option)
const
562 if (qobject_cast<const QListView*>(option.widget) || verticalLayout(option))
569QPixmap KFileItemDelegate::Private::applyHoverEffect(
const QPixmap &icon)
const
582void KFileItemDelegate::Private::gotNewIcon(
const QModelIndex& index)
584 animationHandler->gotNewIcon(index);
589 animationHandler->restartAnimation(state);
592KIO::AnimationState *KFileItemDelegate::Private::animationState(
const QStyleOptionViewItemV4 &option,
593 const QModelIndex &index,
594 const QAbstractItemView *view)
const
601 return animationHandler->animationState(option, index, view);
607QPixmap KFileItemDelegate::Private::transition(
const QPixmap &from,
const QPixmap &to, qreal amount)
const
609 int value = int(0xff * amount);
611 if (value == 0 || to.isNull())
614 if (value == 0xff || from.isNull())
618 color.setAlphaF(amount);
622 const bool usePixmap =
false;
624 const bool usePixmap = from.paintEngine()->hasFeature(QPaintEngine::PorterDuff) &&
625 from.paintEngine()->hasFeature(QPaintEngine::BlendModes);
631 QPixmap under = from;
636 p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
637 p.fillRect(over.rect(), color);
641 p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
642 p.fillRect(under.rect(), color);
643 p.setCompositionMode(QPainter::CompositionMode_Plus);
644 p.drawPixmap(0, 0, over);
649#if defined(Q_WS_X11) && defined(HAVE_XRENDER)
650 else if (from.paintEngine()->hasFeature(QPaintEngine::PorterDuff))
663 QPixmap source(to), destination(from);
666 destination.detach();
668 Display *dpy = QX11Info::display();
670 XRenderPictFormat *format = XRenderFindStandardFormat(dpy, PictStandardA8);
671 XRenderPictureAttributes pa;
675 Pixmap pixmap = XCreatePixmap(dpy, destination.handle(), 1, 1, 8);
676 Picture alpha = XRenderCreatePicture(dpy, pixmap, format, CPRepeat, &pa);
677 XFreePixmap(dpy, pixmap);
681 xcolor.alpha = quint16(0xffff * amount);
682 XRenderFillRectangle(dpy, PictOpSrc, alpha, &xcolor, 0, 0, 1, 1);
685 XRenderComposite(dpy, PictOpOutReverse, alpha, None, destination.x11PictureHandle(),
686 0, 0, 0, 0, 0, 0, destination.width(), destination.height());
689 XRenderComposite(dpy, PictOpAdd, source.x11PictureHandle(), alpha,
690 destination.x11PictureHandle(),
691 0, 0, 0, 0, 0, 0, destination.width(), destination.height());
693 XRenderFreePicture(dpy, alpha);
700 QImage under = from.toImage();
701 QImage over = to.toImage();
705 p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
706 p.fillRect(over.rect(), color);
710 p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
711 p.fillRect(under.rect(), color);
712 p.setCompositionMode(QPainter::CompositionMode_Plus);
713 p.drawImage(0, 0, over);
716 return QPixmap::fromImage(under);
721void KFileItemDelegate::Private::layoutTextItems(
const QStyleOptionViewItemV4 &option,
const QModelIndex &index,
722 QTextLayout *labelLayout, QTextLayout *infoLayout,
723 QRect *textBoundingRect)
const
726 const QString info = information(option, index, item);
727 bool showInformation =
false;
729 setLayoutOptions(*labelLayout, option);
731 const QRect textArea = labelRectangle(option);
732 QRect textRect = subtractMargin(textArea, Private::TextMargin);
735 QSize maxLabelSize = textRect.size();
736 QSize maxInfoSize = textRect.size();
742 if (!info.isEmpty() && textRect.height() >= option.fontMetrics.lineSpacing() * 2)
744 infoLayout->setFont(labelLayout->font());
745 infoLayout->setTextOption(labelLayout->textOption());
747 maxLabelSize.rheight() -= option.fontMetrics.lineSpacing();
748 showInformation =
true;
752 labelSize = layoutText(*labelLayout, option, option.text, maxLabelSize);
753 maxInfoSize.rheight() -= labelSize.height();
757 infoSize = layoutText(*infoLayout, option, info, maxInfoSize);
759 infoSize = QSize(0, 0);
762 const QSize size(qMax(labelSize.width(), infoSize.width()), labelSize.height() + infoSize.height());
763 *textBoundingRect = QStyle::alignedRect(option.direction, option.displayAlignment, size, textRect);
766 labelLayout->setPosition(QPointF(textRect.x(), textBoundingRect->y()));
767 infoLayout->setPosition(QPointF(textRect.x(), textBoundingRect->y() + labelSize.height()));
771void KFileItemDelegate::Private::drawTextItems(QPainter *painter,
const QTextLayout &labelLayout,
772 const QTextLayout &infoLayout,
const QRect &boundingRect)
const
774 if (shadowColor.alpha() > 0)
776 QPixmap pixmap(boundingRect.size());
777 pixmap.fill(Qt::transparent);
780 p.translate(-boundingRect.topLeft());
781 p.setPen(painter->pen());
782 labelLayout.draw(&p, QPoint());
784 if (!infoLayout.text().isEmpty())
786 QColor color = p.pen().color();
787 color.setAlphaF(0.6);
790 infoLayout.draw(&p, QPoint());
794 int padding = qCeil(shadowBlur);
795 int blurFactor = qRound(shadowBlur);
797 QImage image(boundingRect.size() + QSize(padding * 2, padding * 2), QImage::Format_ARGB32_Premultiplied);
800 p.drawImage(padding, padding, pixmap.toImage());
805 painter->drawImage(boundingRect.topLeft() - QPoint(padding, padding) + shadowOffset.toPoint(), image);
806 painter->drawPixmap(boundingRect.topLeft(), pixmap);
810 labelLayout.draw(painter, QPoint());
812 if (!infoLayout.text().isEmpty())
817 QColor color = painter->pen().color();
818 color.setAlphaF(0.6);
820 painter->setPen(color);
821 infoLayout.draw(painter, QPoint());
826void KFileItemDelegate::Private::initStyleOption(QStyleOptionViewItemV4 *option,
827 const QModelIndex &index)
const
830 bool updateFontMetrics =
false;
833 QVariant value = index.data(Qt::FontRole);
834 if (value.isValid()) {
835 option->font = qvariant_cast<QFont>(value).resolve(option->font);
836 updateFontMetrics =
true;
841 option->font.setItalic(
true);
842 updateFontMetrics =
true;
845 if (updateFontMetrics)
846 option->fontMetrics = QFontMetrics(option->font);
849 value = index.data(Qt::TextAlignmentRole);
851 option->displayAlignment = Qt::Alignment(value.toInt());
853 value = index.data(Qt::BackgroundRole);
855 option->backgroundBrush = brush(value, *option);
857 option->text = display(index);
858 if (!option->text.isEmpty())
859 option->features |= QStyleOptionViewItemV2::HasDisplay;
861 option->icon = decoration(*option, index);
862 if (!option->icon.isNull())
863 option->features |= QStyleOptionViewItemV2::HasDecoration;
866 option->showDecorationSelected =
true;
869void KFileItemDelegate::Private::paintJobTransfers(QPainter *painter,
const qreal &jobAnimationAngle,
const QPoint &iconPos,
const QStyleOptionViewItemV4& opt)
872 QSize iconSize = opt.icon.actualSize(opt.decorationSize);
873 QPixmap downArrow = downArrowIcon.pixmap(iconSize * 0.30);
875 QPoint bottomRightCorner = QPoint(iconPos.x() + iconSize.width() * 0.75, iconPos.y() + iconSize.height() * 0.60);
877 QPainter pixmapPainter(&downArrow);
879 pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
880 pixmapPainter.fillRect(downArrow.rect(), QColor(255, 255, 255, 110));
883 painter->translate(bottomRightCorner);
885 painter->drawPixmap(-downArrow.size().width() * .50, -downArrow.size().height() * .50, downArrow);
888 painter->rotate(jobAnimationAngle);
889 painter->setPen(QColor(20, 20, 20, 80));
890 painter->setBrush(QColor(250, 250, 250, 90));
892 int radius = iconSize.width() * 0.04;
893 int spacing = radius * 4.5;
896 painter->drawEllipse(QPoint(-spacing, 0), radius, radius);
898 painter->drawEllipse(QPoint(spacing, 0), radius, radius);
900 painter->drawEllipse(QPoint(0, -spacing), radius, radius);
902 painter->drawEllipse(QPoint(0, spacing), radius, radius);
913 int focusHMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin);
914 int focusVMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameVMargin);
917 const int textMargin = focusHMargin * 4;
918 if (QApplication::isRightToLeft())
919 d->setHorizontalMargin(Private::TextMargin, textMargin, focusVMargin, focusHMargin, focusVMargin);
921 d->setHorizontalMargin(Private::TextMargin, focusHMargin, focusVMargin, textMargin, focusVMargin);
923 d->setHorizontalMargin(Private::IconMargin, focusHMargin, focusVMargin);
924 d->setHorizontalMargin(Private::ItemMargin, 0, 0);
927 d->setVerticalMargin(Private::TextMargin, 6, 2);
928 d->setVerticalMargin(Private::IconMargin, focusHMargin, focusVMargin);
929 d->setVerticalMargin(Private::ItemMargin, 0, 0);
944 const QVariant value = index.data(Qt::SizeHintRole);
946 return qvariant_cast<QSize>(value);
948 QStyleOptionViewItemV4 opt(option);
949 d->initStyleOption(&opt, index);
950 d->setActiveMargins(d->verticalLayout(opt) ? Qt::Vertical : Qt::Horizontal);
952 const QSize displaySize = d->displaySizeHint(opt, index);
953 const QSize decorationSize = d->decorationSizeHint(opt, index);
957 if (d->verticalLayout(opt))
959 size.rwidth() = qMax(displaySize.width(), decorationSize.width());
960 size.rheight() = decorationSize.height() + displaySize.height() + 1;
964 size.rwidth() = decorationSize.width() + displaySize.width() + 1;
965 size.rheight() = qMax(decorationSize.height(), displaySize.height());
968 size = d->addMargin(size, Private::ItemMargin);
969 if (!d->maximumSize.isEmpty())
971 size = size.boundedTo(d->maximumSize);
978QString KFileItemDelegate::Private::display(
const QModelIndex &index)
const
980 const QVariant value = index.data(Qt::DisplayRole);
982 switch (value.type())
984 case QVariant::String:
987 return itemSize(index, fileItem(index));
989 const QString text = replaceNewlines(value.toString());
994 case QVariant::Double:
1009 d->informationList = list;
1024 return d->informationList;
1030 d->shadowColor = color;
1036 return d->shadowColor;
1042 d->shadowOffset = offset;
1048 return d->shadowOffset;
1054 d->shadowBlur = factor;
1060 return d->shadowBlur;
1066 d->maximumSize = size;
1072 return d->maximumSize;
1078 d->showToolTipWhenElided = showToolTip;
1084 return d->showToolTipWhenElided;
1090 d->wrapMode = wrapMode;
1101 QStyleOptionViewItemV4 opt(option);
1102 d->initStyleOption(&opt, index);
1103 return QRect(d->iconPosition(opt), opt.icon.actualSize(opt.decorationSize));
1109 d->downArrowIcon =
KIcon(
"go-down");
1110 d->jobTransfersVisible = jobTransfersVisible;
1116 return d->jobTransfersVisible;
1120QIcon KFileItemDelegate::Private::decoration(
const QStyleOptionViewItemV4 &option,
const QModelIndex &index)
const
1122 const QVariant value = index.data(Qt::DecorationRole);
1125 switch (value.type())
1127 case QVariant::Icon:
1128 icon = qvariant_cast<QIcon>(value);
1131 case QVariant::Pixmap:
1132 icon.addPixmap(qvariant_cast<QPixmap>(value));
1135 case QVariant::Color: {
1136 QPixmap pixmap(option.decorationSize);
1137 pixmap.fill(qvariant_cast<QColor>(value));
1138 icon.addPixmap(pixmap);
1150QRect KFileItemDelegate::Private::labelRectangle(
const QStyleOptionViewItemV4 &option)
const
1152 if (option.icon.isNull())
1153 return subtractMargin(option.rect, Private::ItemMargin);
1155 const QSize decoSize = addMargin(option.decorationSize, Private::IconMargin);
1156 const QRect itemRect = subtractMargin(option.rect, Private::ItemMargin);
1157 QRect textArea(QPoint(0, 0), itemRect.size());
1159 switch (option.decorationPosition)
1161 case QStyleOptionViewItem::Top:
1162 textArea.setTop(decoSize.height() + 1);
1165 case QStyleOptionViewItem::Bottom:
1166 textArea.setBottom(itemRect.height() - decoSize.height() - 1);
1169 case QStyleOptionViewItem::Left:
1170 textArea.setLeft(decoSize.width() + 1);
1173 case QStyleOptionViewItem::Right:
1174 textArea.setRight(itemRect.width() - decoSize.width() - 1);
1178 textArea.translate(itemRect.topLeft());
1179 return QStyle::visualRect(option.direction, option.rect, textArea);
1183QPoint KFileItemDelegate::Private::iconPosition(
const QStyleOptionViewItemV4 &option)
const
1185 const QRect itemRect = subtractMargin(option.rect, Private::ItemMargin);
1186 Qt::Alignment alignment;
1189 switch (option.decorationPosition)
1191 case QStyleOptionViewItem::Top:
1192 alignment = Qt::AlignHCenter | Qt::AlignTop;
1195 case QStyleOptionViewItem::Bottom:
1196 alignment = Qt::AlignHCenter | Qt::AlignBottom;
1199 case QStyleOptionViewItem::Left:
1200 alignment = Qt::AlignVCenter | Qt::AlignLeft;
1203 case QStyleOptionViewItem::Right:
1204 alignment = Qt::AlignVCenter | Qt::AlignRight;
1209 const QSize size = addMargin(option.decorationSize, Private::IconMargin);
1210 const QRect rect = QStyle::alignedRect(option.direction, alignment, size, itemRect);
1213 QRect iconRect = QRect(QPoint(), option.icon.actualSize(option.decorationSize));
1214 iconRect.moveCenter(rect.center());
1216 return iconRect.topLeft();
1220void KFileItemDelegate::Private::drawFocusRect(QPainter *painter,
const QStyleOptionViewItemV4 &option,
1221 const QRect &rect)
const
1223 if (!(option.state & QStyle::State_HasFocus))
1226 QStyleOptionFocusRect opt;
1227 opt.direction = option.direction;
1228 opt.fontMetrics = option.fontMetrics;
1229 opt.palette = option.palette;
1231 opt.state = option.state | QStyle::State_KeyboardFocusChange | QStyle::State_Item;
1232 opt.backgroundColor = option.palette.color(option.state & QStyle::State_Selected ?
1233 QPalette::Highlight : QPalette::Base);
1236 painter->setRenderHint(QPainter::Antialiasing,
false);
1238 QStyle *style = option.widget ? option.widget->style() : QApplication::style();
1239 style->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, painter, option.widget);
1241 painter->setRenderHint(QPainter::Antialiasing);
1246 const QModelIndex &index)
const
1248 if (!index.isValid())
1251 QStyleOptionViewItemV4 opt(option);
1252 d->initStyleOption(&opt, index);
1253 d->setActiveMargins(d->verticalLayout(opt) ? Qt::Vertical : Qt::Horizontal);
1255 if (!(option.state & QStyle::State_Enabled))
1257 opt.palette.setCurrentColorGroup(QPalette::Disabled);
1261 if (index.column() > 0)
1262 opt.state &= ~QStyle::State_MouseOver;
1264 opt.viewItemPosition = QStyleOptionViewItemV4::OnlyOne;
1266 const QAbstractItemView *view = qobject_cast<const QAbstractItemView*>(opt.widget);
1273 qreal progress = ((opt.state & QStyle::State_MouseOver) &&
1275 const QPoint iconPos = d->iconPosition(opt);
1276 QIcon::Mode iconMode = option.state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled;
1277 QIcon::State iconState = option.state & QStyle::State_Open ? QIcon::On : QIcon::Off;
1278 QPixmap icon = opt.icon.pixmap(opt.decorationSize, iconMode, iconState);
1285 opt.state &= ~QStyle::State_MouseOver;
1293 QPixmap pixmap = d->transition(cache->
regular, cache->
hover, progress);
1299 const QPixmap fadeFromPixmap = d->transition(fadeFromCache->
regular, fadeFromCache->
hover, progress);
1301 pixmap = d->transition(fadeFromPixmap, pixmap, state->
fadeProgress());
1303 painter->drawPixmap(option.rect.topLeft(), pixmap);
1304 if (d->jobTransfersVisible && index.column() == 0) {
1322 d->gotNewIcon(index);
1330 d->gotNewIcon(index);
1337 const QPen pen = QPen(d->foregroundBrush(opt, index), 0);
1342 QTextLayout labelLayout, infoLayout;
1343 QRect textBoundingRect;
1345 d->layoutTextItems(opt, index, &labelLayout, &infoLayout, &textBoundingRect);
1347 QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
1349 int focusHMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin);
1350 int focusVMargin = style->pixelMetric(QStyle::PM_FocusFrameVMargin);
1351 QRect focusRect = textBoundingRect.adjusted(-focusHMargin, -focusVMargin,
1352 +focusHMargin, +focusVMargin);
1364 p.translate(-option.rect.topLeft());
1365 p.setRenderHint(QPainter::Antialiasing);
1367 style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, &p, opt.widget);
1368 p.drawPixmap(iconPos, icon);
1369 d->drawTextItems(&p, labelLayout, infoLayout, textBoundingRect);
1370 d->drawFocusRect(&p, opt, focusRect);
1373 opt.state |= QStyle::State_MouseOver;
1374 icon = d->applyHoverEffect(icon);
1376 p.begin(&cache->
hover);
1377 p.translate(-option.rect.topLeft());
1378 p.setRenderHint(QPainter::Antialiasing);
1380 style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, &p, opt.widget);
1381 p.drawPixmap(iconPos, icon);
1382 d->drawTextItems(&p, labelLayout, infoLayout, textBoundingRect);
1383 d->drawFocusRect(&p, opt, focusRect);
1388 QPixmap pixmap = d->transition(cache->
regular, cache->
hover, progress);
1394 const QPixmap fadeFromPixmap = d->transition(fadeFromCache->
regular, fadeFromCache->
hover, progress);
1396 pixmap = d->transition(fadeFromPixmap, pixmap, state->
fadeProgress());
1398 d->restartAnimation(state);
1401 painter->drawPixmap(option.rect.topLeft(), pixmap);
1402 painter->setRenderHint(QPainter::Antialiasing);
1403 if (d->jobTransfersVisible && index.column() == 0) {
1415 painter->setRenderHint(QPainter::Antialiasing);
1416 painter->setPen(pen);
1418 if (progress > 0 && !(opt.state & QStyle::State_MouseOver))
1420 opt.state |= QStyle::State_MouseOver;
1421 icon = d->applyHoverEffect(icon);
1424 style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget);
1425 painter->drawPixmap(iconPos, icon);
1427 d->drawTextItems(painter, labelLayout, infoLayout, textBoundingRect);
1428 d->drawFocusRect(painter, opt, focusRect);
1430 if (d->jobTransfersVisible && index.column() == 0 && state) {
1440 const QModelIndex &index)
const
1442 QStyleOptionViewItemV4 opt(option);
1443 d->initStyleOption(&opt, index);
1446 edit->setAcceptRichText(
false);
1447 edit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1448 edit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1449 edit->setAlignment(opt.displayAlignment);
1450 edit->setEnabled(
false);
1456 const QModelIndex &index)
1469 KTextEdit *textedit = qobject_cast<KTextEdit*>(editor);
1470 Q_ASSERT(textedit != 0);
1475 if(textedit->isEnabled()) {
1478 textedit->setEnabled(
true);
1480 const QVariant value = index.data(Qt::EditRole);
1481 const QString text = value.toString();
1482 textedit->insertPlainText(text);
1483 textedit->selectAll();
1486 if (!extension.isEmpty()) {
1489 const int selectionLength = text.length() - extension.length() - 1;
1490 QTextCursor cursor = textedit->textCursor();
1491 cursor.movePosition(QTextCursor::StartOfBlock);
1492 cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, selectionLength);
1493 textedit->setTextCursor(cursor);
1500 KTextEdit *textedit = qobject_cast<KTextEdit*>(editor);
1501 Q_ASSERT(textedit != 0);
1503 model->setData(index, textedit->toPlainText(), Qt::EditRole);
1508 const QModelIndex &index)
const
1510 QStyleOptionViewItemV4 opt(option);
1511 d->initStyleOption(&opt, index);
1512 d->setActiveMargins(d->verticalLayout(opt) ? Qt::Vertical : Qt::Horizontal);
1514 QRect r = d->labelRectangle(opt);
1517 if (!d->maximumSize.isEmpty()) {
1518 if (d->verticalLayout(option)) {
1519 int diff = qMax(r.width(), d->maximumSize.width()) - r.width();
1521 r.adjust(-(diff / 2), 0, diff / 2, 0);
1525 int diff = qMax(r.width(), d->maximumSize.width() - opt.decorationSize.width()) - r.width();
1527 if (opt.decorationPosition == QStyleOptionViewItem::Left) {
1528 r.adjust(0, 0, diff, 0);
1531 r.adjust(-diff, 0, 0, 0);
1537 KTextEdit *textedit = qobject_cast<KTextEdit*>(editor);
1538 Q_ASSERT(textedit != 0);
1539 const int frame = textedit->frameWidth();
1540 r.adjust(-frame, -frame, frame, frame);
1542 editor->setGeometry(r);
1547 const QModelIndex &index)
1554 const QVariant toolTip = index.data(Qt::ToolTipRole);
1556 if (!toolTip.isValid()) {
1560 if (index.data() != toolTip) {
1561 return QAbstractItemDelegate::helpEvent(event, view, option, index);
1564 if (!d->showToolTipWhenElided) {
1570 QStyleOptionViewItemV4 opt(option);
1571 d->initStyleOption(&opt, index);
1572 d->setActiveMargins(d->verticalLayout(opt) ? Qt::Vertical : Qt::Horizontal);
1574 QTextLayout labelLayout;
1575 QTextLayout infoLayout;
1576 QRect textBoundingRect;
1577 d->layoutTextItems(opt, index, &labelLayout, &infoLayout, &textBoundingRect);
1578 const QString elidedText = d->elidedText(labelLayout, opt, textBoundingRect.size());
1580 if (elidedText != d->display(index)) {
1581 return QAbstractItemDelegate::helpEvent(event, view, option, index);
1589 QStyleOptionViewItemV4 opt(option);
1590 d->initStyleOption(&opt, index);
1591 d->setActiveMargins(d->verticalLayout(opt) ? Qt::Vertical : Qt::Horizontal);
1593 QTextLayout labelLayout;
1594 QTextLayout infoLayout;
1595 QRect textBoundingRect;
1596 d->layoutTextItems(opt, index, &labelLayout, &infoLayout, &textBoundingRect);
1598 const QPoint pos = d->iconPosition(opt);
1599 QRect iconRect = QRect(pos, opt.icon.actualSize(opt.decorationSize));
1602 switch (opt.decorationPosition)
1604 case QStyleOptionViewItem::Top:
1605 if (iconRect.width() < textBoundingRect.width())
1606 iconRect.setBottom(textBoundingRect.top());
1608 textBoundingRect.setTop(iconRect.bottom());
1610 case QStyleOptionViewItem::Bottom:
1611 if (iconRect.width() < textBoundingRect.width())
1612 iconRect.setTop(textBoundingRect.bottom());
1614 textBoundingRect.setBottom(iconRect.top());
1616 case QStyleOptionViewItem::Left:
1617 iconRect.setRight(textBoundingRect.left());
1619 case QStyleOptionViewItem::Right:
1620 iconRect.setLeft(textBoundingRect.right());
1626 region += textBoundingRect;
1632 KTextEdit *editor = qobject_cast<KTextEdit*>(
object);
1636 switch (event->type())
1638 case QEvent::KeyPress:
1640 QKeyEvent *keyEvent =
static_cast<QKeyEvent*
>(event);
1641 switch (keyEvent->key())
1644 case Qt::Key_Backtab:
1645 emit commitData(editor);
1646 emit closeEditor(editor, NoHint);
1650 case Qt::Key_Return: {
1651 const QString text = editor->toPlainText();
1652 if (text.isEmpty() || (text == QLatin1String(
".")) || (text == QLatin1String(
"..")))
1655 emit commitData(editor);
1656 emit closeEditor(editor, SubmitModelCache);
1660 case Qt::Key_Escape:
1661 emit closeEditor(editor, RevertModelCache);
1669 case QEvent::FocusOut:
1671 const QWidget *w = QApplication::activePopupWidget();
1672 if (!w || w->parent() != editor)
1674 emit commitData(editor);
1675 emit closeEditor(editor, NoHint);
1689#include "kfileitemdelegate.moc"
@ FileItemRole
returns the KFileItem for a given index
@ ChildCountRole
returns the number of items in a directory, or ChildCountUnknown
@ HasJobRole
returns whether or not there is a job on an item (file/directory)
KFileItemDelegate is intended to be used to provide a KDE file system view, when using one of the sta...
void setShowInformation(const InformationList &list)
Sets the list of information lines that are shown below the icon label in list views.
void setShadowColor(const QColor &color)
Sets the color used for drawing the text shadow.
QPointF shadowOffset
This property holds the horizontal and vertical offset for the text shadow.
QColor shadowColor
This property holds the color used for the text shadow.
virtual void setEditorData(QWidget *editor, const QModelIndex &index) const
Reimplemented from QAbstractItemDelegate.
InformationList information
This property holds which additional information (if any) should be shown below items in icon views.
void setShadowOffset(const QPointF &offset)
Sets the horizontal and vertical offset for the text shadow.
qreal shadowBlur
This property holds the blur radius for the text shadow.
void setMaximumSize(const QSize &size)
Sets the maximum size for KFileItemDelegate::sizeHint().
virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
Reimplemented from QAbstractItemDelegate.
void setWrapMode(QTextOption::WrapMode wrapMode)
When the contents text needs to be wrapped, wrapMode strategy will be followed.
QRect iconRect(const QStyleOptionViewItem &option, const QModelIndex &index) const
Returns the rectangle of the icon that is aligned inside the decoration rectangle.
virtual ~KFileItemDelegate()
Destroys the item delegate.
Information
This enum defines the additional information that can be displayed below item labels in icon views.
@ Comment
A simple comment that can be displayed to the user as is.
@ OctalPermissions
The permissions as an octal value, e.g. 0644.
@ OwnerAndGroup
The user and group that owns the file, e.g. root:root.
@ LocalPathOrUrl
The local path to the file or the URL in case it is not a local file.
@ AccessTime
The date and time the file/folder was last accessed.
@ FriendlyMimeType
The descriptive name for the mime type, e.g. HTML Document.
@ CreationTime
The date and time the file/folder was created.
@ ModificationTime
The date and time the file/folder was last modified.
@ Permissions
A UNIX permissions string, e.g. -rwxr-xr-x.
@ Size
The file size for files, and the number of items for folders.
@ MimeType
The mime type for the item, e.g. text/html.
@ LinkDest
The destination of a symbolic link.
@ NoInformation
No additional information will be shown for items.
@ Owner
The user name of the file owner, e.g. root.
KFileItemDelegate(QObject *parent=0)
Constructs a new KFileItemDelegate.
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
Paints the item indicated by index, using painter.
QSize maximumSize
This property holds the maximum size that can be returned by KFileItemDelegate::sizeHint().
bool showToolTipWhenElided
This property determines whether a tooltip will be shown by the delegate if the display role is elide...
virtual bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
Reimplemented from QAbstractItemDelegate.
void setJobTransfersVisible(bool jobTransfersVisible)
Enable/Disable the displaying of an animated overlay that is shown for any destination urls (in the v...
bool helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &index)
Reimplemented from QAbstractItemDelegate.
void setShadowBlur(qreal radius)
Sets the blur radius for the text shadow.
bool jobTransfersVisible
This property determines if there are KIO jobs on a destination URL visible, then they will have a sm...
InformationList showInformation() const
Returns the file item information that should be shown below item labels in list views.
virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
Reimplemented from QAbstractItemDelegate.
void setShowToolTipWhenElided(bool showToolTip)
Sets whether a tooltip should be shown if the display role is elided containing the full display role...
QTextOption::WrapMode wrapMode() const
Returns the wrapping strategy followed to show text when it needs wrapping.
virtual bool eventFilter(QObject *object, QEvent *event)
Reimplemented from QAbstractItemDelegate.
QRegion shape(const QStyleOptionViewItem &option, const QModelIndex &index)
Returns the shape of the item as a region.
virtual QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
Reimplemented from QAbstractItemDelegate.
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
Returns the nominal size for the item referred to by index, given the provided options.
A KFileItem is a generic class to handle a file, local or remote.
QString comment() const
A comment which can contain anything - even rich text.
bool isMimeTypeKnown() const
QString user() const
Returns the owner of the file.
KIO::filesize_t size() const
Returns the size of the file, if known.
bool isLink() const
Returns true if this item represents a link in the UNIX sense of a link.
QString mimetype() const
Returns the mimetype of the file item.
mode_t permissions() const
Returns the permissions of the file (stat.st_mode containing only permissions).
QString group() const
Returns the group of the file.
bool isFile() const
Returns true if this item represents a file (and not a a directory)
QString linkDest() const
Returns the link destination if isLink() == true.
QString localPath() const
Returns the local path if isLocalFile() == true or the KIO item has a UDS_LOCAL_PATH atom.
bool isNull() const
Return true if default-constructed.
KUrl url() const
Returns the url of the file.
QString permissionsString() const
Returns the access permissions for the file as a string.
QString timeString(FileTimes which=ModificationTime) const
Requests the modification, access or creation time as a string, depending on which.
QString mimeComment() const
Returns the user-readable string representing the type of this file, like "OpenDocument Text File".
static GraphicEffects graphicEffectsLevel()
CachedRendering * takeCachedRendering()
void setCachedRenderingFadeFrom(CachedRendering *rendering)
qreal hoverProgress() const
void setCachedRendering(CachedRendering *rendering)
bool hasJobAnimation() const
CachedRendering * cachedRendering() const
qreal jobAnimationAngle() const
CachedRendering * cachedRenderingFadeFrom() const
qreal fadeProgress() const
bool checkValidity(QStyle::State current) const
static void shadowBlur(QImage &image, float radius, const QColor &color)
QImage apply(const QImage &src, int effect, float value, const QColor &rgb, bool trans) const
bool hasEffect(int group, int state) const
static KIconLoader * global()
KIconEffect * iconEffect() const
QString formatNumber(const QString &numStr, bool round=true, int precision=-1) const
QString formatLong(long num) const
QString formatByteSize(double size) const
static QString extractKnownExtension(const QString &fileName)
QString pathOrUrl() const
QString i18nc(const char *ctxt, const char *text)
QString i18ncp(const char *ctxt, const char *sing, const char *plur, const A1 &a1)
A namespace for KIO globals.
QString label(StandardShortcut id)
QString preProcessWrap(const QString &text)