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
223 return KGlobal::locale()->formatByteSize(item.
size());
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());
990 return KStringHandler::preProcessWrap(text);
994 case QVariant::Double:
995 return KGlobal::locale()->formatNumber(value.toDouble());
999 return KGlobal::locale()->formatLong(value.toInt());
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"