28 #include <QApplication>
30 #include <QModelIndex>
34 #include <QPainterPath>
35 #include <QTextLayout>
37 #include <QPaintEngine>
54 #if defined(Q_WS_X11) && defined(HAVE_XRENDER)
55 # include <X11/Xlib.h>
56 # include <X11/extensions/Xrender.h>
65 int left, right, top, bottom;
69 class 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;
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,
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;
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);
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)
149 void KFileItemDelegate::Private::setActiveMargins(Qt::Orientation layout)
151 activeMargins = (layout == Qt::Horizontal ?
152 horizontalMargin : verticalMargin);
156 void 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;
165 void 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;
174 void KFileItemDelegate::Private::setVerticalMargin(MarginType type,
int horizontal,
int vertical)
176 setVerticalMargin(type, horizontal, vertical, horizontal, vertical);
180 void KFileItemDelegate::Private::setHorizontalMargin(MarginType type,
int horizontal,
int vertical)
182 setHorizontalMargin(type, horizontal, vertical, horizontal, vertical);
186 QRect 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);
194 QRect 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);
202 QSize 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);
210 QSize 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);
219 QString KFileItemDelegate::Private::itemSize(
const QModelIndex &index,
const KFileItem &item)
const
236 return i18ncp(
"Items in a folder",
"1 item",
"%1 items", count);
241 QString 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);
272 string += item.
user();
276 string += item.
user() +
':' + item.
group();
324 KFileItem KFileItemDelegate::Private::fileItem(
const QModelIndex &index)
const
332 QString KFileItemDelegate::Private::replaceNewlines(
const QString &text)
const
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;
346 QSize KFileItemDelegate::Private::layoutText(QTextLayout &layout,
const QStyleOptionViewItemV4 &option,
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());
362 QSize 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);
391 QString 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();
441 void 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);
453 QSize KFileItemDelegate::Private::displaySizeHint(
const QStyleOptionViewItemV4 &option,
454 const QModelIndex &index)
const
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);
495 QSize 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);
512 bool KFileItemDelegate::Private::verticalLayout(const QStyleOptionViewItemV4 &option)
const
515 option.decorationPosition == QStyleOptionViewItem::Bottom);
520 QBrush 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);
538 QBrush 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);
560 bool KFileItemDelegate::Private::isListView(
const QStyleOptionViewItemV4 &option)
const
562 if (qobject_cast<const QListView*>(option.widget) || verticalLayout(option))
569 QPixmap KFileItemDelegate::Private::applyHoverEffect(
const QPixmap &icon)
const
582 void KFileItemDelegate::Private::gotNewIcon(
const QModelIndex& index)
584 animationHandler->gotNewIcon(index);
589 animationHandler->restartAnimation(state);
592 KIO::AnimationState *KFileItemDelegate::Private::animationState(
const QStyleOptionViewItemV4 &option,
593 const QModelIndex &index,
594 const QAbstractItemView *view)
const
601 return animationHandler->animationState(option, index, view);
607 QPixmap 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);
621 #if defined(Q_OS_MAC)
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);
721 void 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()));
771 void 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());
826 void 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;
869 void 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);
911 : QAbstractItemDelegate(parent), d(new Private(this))
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);
978 QString 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;
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");
1116 return d->jobTransfersVisible;
1120 QIcon 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);
1150 QRect 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);
1159 switch (option.decorationPosition)
1162 textArea.setTop(decoSize.height() + 1);
1165 case QStyleOptionViewItem::Bottom:
1166 textArea.setBottom(itemRect.height() - decoSize.height() - 1);
1170 textArea.setLeft(decoSize.width() + 1);
1174 textArea.setRight(itemRect.width() - decoSize.width() - 1);
1178 textArea.translate(itemRect.topLeft());
1179 return QStyle::visualRect(option.direction, option.rect, textArea);
1183 QPoint KFileItemDelegate::Private::iconPosition(
const QStyleOptionViewItemV4 &option)
const
1185 const QRect itemRect = subtractMargin(option.rect, Private::ItemMargin);
1186 Qt::Alignment alignment;
1189 switch (option.decorationPosition)
1192 alignment = Qt::AlignHCenter | Qt::AlignTop;
1195 case QStyleOptionViewItem::Bottom:
1196 alignment = Qt::AlignHCenter | Qt::AlignBottom;
1200 alignment = Qt::AlignVCenter | Qt::AlignLeft;
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();
1220 void 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)
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();
1485 const QString extension = KMimeType::extractKnownExtension(text);
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);
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();
1528 r.adjust(0, 0, diff, 0);
1531 r.adjust(-diff, 0, 0, 0);
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)
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());
1617 iconRect.setRight(textBoundingRect.left());
1620 iconRect.setLeft(textBoundingRect.right());
1626 region += textBoundingRect;
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"
QRegion shape(const QStyleOptionViewItem &option, const QModelIndex &index)
Returns the shape of the item as a region.
The destination of a symbolic link.
virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
Reimplemented from QAbstractItemDelegate.
The local path to the file or the URL in case it is not a local file.
static KIconLoader * global()
void setMaximumSize(const QSize &size)
Sets the maximum size for KFileItemDelegate::sizeHint().
qreal hoverProgress() const
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.
QString mimetype() const
Returns the mimetype of the file item.
QString user() const
Returns the owner of the file.
InformationList showInformation() const
Returns the file item information that should be shown below item labels in list views.
The date and time the file/folder was last accessed.
A simple comment that can be displayed to the user as is.
The permissions as an octal value, e.g. 0644.
bool isNull() const
Return true if default-constructed.
virtual void setEditorData(QWidget *editor, const QModelIndex &index) const
Reimplemented from QAbstractItemDelegate.
QString label(StandardShortcut id)
returns the KFileItem for a given index
void setShadowColor(const QColor &color)
Sets the color used for drawing the text shadow.
void setShadowBlur(qreal radius)
Sets the blur radius for the text shadow.
virtual bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
Reimplemented from QAbstractItemDelegate.
The user name of the file owner, e.g. root.
QString formatLong(long num) const
Mode
Possible image file access modes.
returns whether or not there is a job on an item (file/directory)
QList< Information > InformationList
QString comment() const
A comment which can contain anything - even rich text.
mode_t permissions() const
Returns the permissions of the file (stat.st_mode containing only permissions).
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
Paints the item indicated by index, using painter.
QRect iconRect(const QStyleOptionViewItem &option, const QModelIndex &index) const
Returns the rectangle of the icon that is aligned inside the decoration rectangle.
The user and group that owns the file, e.g. root:root.
returns the number of items in a directory, or ChildCountUnknown
qreal jobAnimationAngle() const
Information
This enum defines the additional information that can be displayed below item labels in icon views...
QString i18nc(const char *ctxt, const char *text)
bool showToolTipWhenElided() const
Returns whether a tooltip should be shown if the display role is elided containing the full display r...
void setJobTransfersVisible(bool jobTransfersVisible)
Enable/Disable the displaying of an animated overlay that is shown for any destination urls (in the v...
virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
Reimplemented from QAbstractItemDelegate.
void setCachedRendering(CachedRendering *rendering)
bool jobTransfersVisible() const
Returns whether or not the displaying of job transfers is enabled.
bool hasJobAnimation() const
bool helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &index)
Reimplemented from QAbstractItemDelegate.
void setWrapMode(QTextOption::WrapMode wrapMode)
When the contents text needs to be wrapped, wrapMode strategy will be followed.
QString preProcessWrap(const QString &text)
QString i18ncp(const char *ctxt, const char *sing, const char *plur, const A1 &a1)
QString localPath() const
Returns the local path if isLocalFile() == true or the KIO item has a UDS_LOCAL_PATH atom...
QString linkDest() const
Returns the link destination if isLink() == true.
void setShadowOffset(const QPointF &offset)
Sets the horizontal and vertical offset for the text shadow.
QString pathOrUrl() const
No additional information will be shown for items.
QString formatByteSize(double size) const
virtual QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
Reimplemented from QAbstractItemDelegate.
QString mimeComment() const
Returns the user-readable string representing the type of this file, like "OpenDocument Text File"...
CachedRendering * cachedRenderingFadeFrom() const
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.
bool isFile() const
Returns true if this item represents a file (and not a a directory)
QString group() const
Returns the group of the file.
KIO::filesize_t size() const
Returns the size of the file, if known.
QString permissionsString() const
Returns the access permissions for the file as a string.
qreal fadeProgress() const
InformationList information
This property holds which additional information (if any) should be shown below items in icon views...
KIconEffect * iconEffect() const
The descriptive name for the mime type, e.g. HTML Document.
bool isLink() const
Returns true if this item represents a link in the UNIX sense of a link.
The date and time the file/folder was created.
QPointF shadowOffset() const
Returns the offset used for the text shadow.
The mime type for the item, e.g. text/html.
QSize maximumSize() const
Returns the maximum size for KFileItemDelegate::sizeHint().
The date and time the file/folder was last modified.
bool hasEffect(int group, int state) const
bool checkValidity(QStyle::State current) const
KFileItemDelegate is intended to be used to provide a KDE file system view, when using one of the sta...
CachedRendering * cachedRendering() const
void setCachedRenderingFadeFrom(CachedRendering *rendering)
QString timeString(FileTimes which=ModificationTime) const
Requests the modification, access or creation time as a string, depending on which.
void setShowToolTipWhenElided(bool showToolTip)
Sets whether a tooltip should be shown if the display role is elided containing the full display role...
KFileItemDelegate(QObject *parent=0)
Constructs a new KFileItemDelegate.
The file size for files, and the number of items for folders.
A UNIX permissions string, e.g. -rwxr-xr-x.
QImage apply(const QImage &src, int group, int state) const
static GraphicEffects graphicEffectsLevel()
bool isMimeTypeKnown() const
QColor shadowColor() const
Returns the color used for the text shadow.
QString formatNumber(double num, int precision=-1) const
void setShowInformation(const InformationList &list)
Sets the list of information lines that are shown below the icon label in list views.
qreal shadowBlur() const
Returns the blur radius for the text shadow.
static void shadowBlur(QImage &image, float radius, const QColor &color)
virtual ~KFileItemDelegate()
Destroys the item delegate.
KUrl url() const
Returns the url of the file.
A KFileItem is a generic class to handle a file, local or remote.
CachedRendering * takeCachedRendering()
QString number(KIO::filesize_t size)
Converts a size to a string representation Not unlike QString::number(...)
QStringList list(const QString &fileClass)
Returns a list of directories associated with this file-class.