2 This file is part of the KDE project
4 Copyright © 2006-2007, 2008 Fredrik Höglund <fredrik@kde.org>
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
22 #include "kfileitemdelegate.h"
23 #include "imagefilter_p.h"
25 #include <config.h> // for HAVE_XRENDER
27 #include <QApplication>
29 #include <QModelIndex>
33 #include <QPainterPath>
34 #include <QTextLayout>
36 #include <QPaintEngine>
41 #include <kiconloader.h>
42 #include <kiconeffect.h>
43 #include <kdirmodel.h>
44 #include <kfileitem.h>
45 #include <kcolorscheme.h>
46 #include <kglobalsettings.h>
47 #include <ktextedit.h>
49 #include "delegateanimationhandler_p.h"
51 #if defined(Q_WS_X11) && defined(HAVE_XRENDER)
52 # include <X11/Xlib.h>
53 # include <X11/extensions/Xrender.h>
62 int left
, right
, top
, bottom
;
66 class KFileItemDelegate::Private
69 enum MarginType
{ ItemMargin
= 0, TextMargin
, IconMargin
, NMargins
};
71 Private(KFileItemDelegate
*parent
);
74 QSize
decorationSizeHint(const QStyleOptionViewItemV4
&option
, const QModelIndex
&index
) const;
75 QSize
displaySizeHint(const QStyleOptionViewItemV4
&option
, const QModelIndex
&index
) const;
76 QString
replaceNewlines(const QString
&string
) const;
77 inline KFileItem
fileItem(const QModelIndex
&index
) const;
78 QString
elidedText(QTextLayout
&layout
, const QStyleOptionViewItemV4
&option
, const QSize
&maxSize
) const;
79 QSize
layoutText(QTextLayout
&layout
, const QStyleOptionViewItemV4
&option
,
80 const QString
&text
, const QSize
&constraints
) const;
81 QSize
layoutText(QTextLayout
&layout
, const QString
&text
, int maxWidth
) const;
82 inline void setLayoutOptions(QTextLayout
&layout
, const QStyleOptionViewItemV4
&options
) const;
83 inline bool verticalLayout(const QStyleOptionViewItemV4
&option
) const;
84 inline QBrush
brush(const QVariant
&value
, const QStyleOptionViewItemV4
&option
) const;
85 QBrush
foregroundBrush(const QStyleOptionViewItemV4
&option
, const QModelIndex
&index
) const;
86 inline void setActiveMargins(Qt::Orientation layout
);
87 void setVerticalMargin(MarginType type
, int left
, int right
, int top
, int bottom
);
88 void setHorizontalMargin(MarginType type
, int left
, int right
, int top
, int bottom
);
89 inline void setVerticalMargin(MarginType type
, int hor
, int ver
);
90 inline void setHorizontalMargin(MarginType type
, int hor
, int ver
);
91 inline QRect
addMargin(const QRect
&rect
, MarginType type
) const;
92 inline QRect
subtractMargin(const QRect
&rect
, MarginType type
) const;
93 inline QSize
addMargin(const QSize
&size
, MarginType type
) const;
94 inline QSize
subtractMargin(const QSize
&size
, MarginType type
) const;
95 QString
itemSize(const QModelIndex
&index
, const KFileItem
&item
) const;
96 QString
information(const QStyleOptionViewItemV4
&option
, const QModelIndex
&index
, const KFileItem
&item
) const;
97 bool isListView(const QStyleOptionViewItemV4
&option
) const;
98 QString
display(const QModelIndex
&index
) const;
99 QIcon
decoration(const QStyleOptionViewItemV4
&option
, const QModelIndex
&index
) const;
100 QPoint
iconPosition(const QStyleOptionViewItemV4
&option
) const;
101 QRect
labelRectangle(const QStyleOptionViewItemV4
&option
) const;
102 void layoutTextItems(const QStyleOptionViewItemV4
&option
, const QModelIndex
&index
,
103 QTextLayout
*labelLayout
, QTextLayout
*infoLayout
, QRect
*textBoundingRect
) const;
104 void drawTextItems(QPainter
*painter
, const QTextLayout
&labelLayout
, const QTextLayout
&infoLayout
,
105 const QRect
&textBoundingRect
) const;
106 KIO::AnimationState
*animationState(const QStyleOptionViewItemV4
&option
, const QModelIndex
&index
,
107 const QAbstractItemView
*view
) const;
108 QPixmap
applyHoverEffect(const QPixmap
&icon
) const;
109 QPixmap
transition(const QPixmap
&from
, const QPixmap
&to
, qreal amount
) const;
110 void initStyleOption(QStyleOptionViewItemV4
*option
, const QModelIndex
&index
) const;
111 void drawFocusRect(QPainter
*painter
, const QStyleOptionViewItemV4
&option
, const QRect
&rect
) const;
114 KFileItemDelegate::InformationList informationList
;
116 QPointF shadowOffset
;
119 bool showToolTipWhenElided
;
122 KFileItemDelegate
* const q
;
123 KIO::DelegateAnimationHandler
*animationHandler
;
124 Margin verticalMargin
[NMargins
];
125 Margin horizontalMargin
[NMargins
];
126 Margin
*activeMargins
;
130 KFileItemDelegate::Private::Private(KFileItemDelegate
*parent
)
131 : shadowColor(Qt::transparent
), shadowOffset(1, 1), shadowBlur(2), maximumSize(0, 0),
132 showToolTipWhenElided(true), q(parent
),
133 animationHandler(new KIO::DelegateAnimationHandler(parent
)), activeMargins(0)
138 void KFileItemDelegate::Private::setActiveMargins(Qt::Orientation layout
)
140 activeMargins
= (layout
== Qt::Horizontal
?
141 horizontalMargin
: verticalMargin
);
145 void KFileItemDelegate::Private::setVerticalMargin(MarginType type
, int left
, int top
, int right
, int bottom
)
147 verticalMargin
[type
].left
= left
;
148 verticalMargin
[type
].right
= right
;
149 verticalMargin
[type
].top
= top
;
150 verticalMargin
[type
].bottom
= bottom
;
154 void KFileItemDelegate::Private::setHorizontalMargin(MarginType type
, int left
, int top
, int right
, int bottom
)
156 horizontalMargin
[type
].left
= left
;
157 horizontalMargin
[type
].right
= right
;
158 horizontalMargin
[type
].top
= top
;
159 horizontalMargin
[type
].bottom
= bottom
;
163 void KFileItemDelegate::Private::setVerticalMargin(MarginType type
, int horizontal
, int vertical
)
165 setVerticalMargin(type
, horizontal
, vertical
, horizontal
, vertical
);
169 void KFileItemDelegate::Private::setHorizontalMargin(MarginType type
, int horizontal
, int vertical
)
171 setHorizontalMargin(type
, horizontal
, vertical
, horizontal
, vertical
);
175 QRect
KFileItemDelegate::Private::addMargin(const QRect
&rect
, MarginType type
) const
177 Q_ASSERT(activeMargins
!= 0);
178 const Margin
&m
= activeMargins
[type
];
179 return rect
.adjusted(-m
.left
, -m
.top
, m
.right
, m
.bottom
);
183 QRect
KFileItemDelegate::Private::subtractMargin(const QRect
&rect
, MarginType type
) const
185 Q_ASSERT(activeMargins
!= 0);
186 const Margin
&m
= activeMargins
[type
];
187 return rect
.adjusted(m
.left
, m
.top
, -m
.right
, -m
.bottom
);
191 QSize
KFileItemDelegate::Private::addMargin(const QSize
&size
, MarginType type
) const
193 Q_ASSERT(activeMargins
!= 0);
194 const Margin
&m
= activeMargins
[type
];
195 return QSize(size
.width() + m
.left
+ m
.right
, size
.height() + m
.top
+ m
.bottom
);
199 QSize
KFileItemDelegate::Private::subtractMargin(const QSize
&size
, MarginType type
) const
201 Q_ASSERT(activeMargins
!= 0);
202 const Margin
&m
= activeMargins
[type
];
203 return QSize(size
.width() - m
.left
- m
.right
, size
.height() - m
.top
- m
.bottom
);
207 // Returns the size of a file, or the number of items in a directory, as a QString
208 QString
KFileItemDelegate::Private::itemSize(const QModelIndex
&index
, const KFileItem
&item
) const
210 // Return a formatted string containing the file size, if the item is a file
212 return KGlobal::locale()->formatByteSize(item
.size());
214 // Return the number of items in the directory
215 const QVariant value
= index
.data(KDirModel::ChildCountRole
);
216 const int count
= value
.type() == QVariant::Int
? value
.toInt() : KDirModel::ChildCountUnknown
;
218 if (count
== KDirModel::ChildCountUnknown
) {
219 // was: i18nc("Items in a folder", "? items");
220 // but this just looks useless in a remote directory listing,
221 // better not show anything.
225 return i18ncp("Items in a folder", "1 item", "%1 items", count
);
229 // Returns the additional information string, if one should be shown, or an empty string otherwise
230 QString
KFileItemDelegate::Private::information(const QStyleOptionViewItemV4
&option
, const QModelIndex
&index
,
231 const KFileItem
&item
) const
235 if (informationList
.isEmpty() || item
.isNull() || !isListView(option
))
238 foreach (KFileItemDelegate::Information info
, informationList
)
240 if (info
== KFileItemDelegate::NoInformation
)
243 if (!string
.isEmpty())
244 string
+= QChar::LineSeparator
;
248 case KFileItemDelegate::Size
:
249 string
+= itemSize(index
, item
);
252 case KFileItemDelegate::Permissions
:
253 string
+= item
.permissionsString();
256 case KFileItemDelegate::OctalPermissions
:
257 string
+= QString('0') + QString::number(item
.permissions(), 8);
260 case KFileItemDelegate::Owner
:
261 string
+= item
.user();
264 case KFileItemDelegate::OwnerAndGroup
:
265 string
+= item
.user() + ':' + item
.group();
268 case KFileItemDelegate::CreationTime
:
269 string
+= item
.timeString(KFileItem::CreationTime
);
272 case KFileItemDelegate::ModificationTime
:
273 string
+= item
.timeString(KFileItem::ModificationTime
);
276 case KFileItemDelegate::AccessTime
:
277 string
+= item
.timeString(KFileItem::AccessTime
);
280 case KFileItemDelegate::MimeType
:
281 string
+= item
.isMimeTypeKnown() ? item
.mimetype() : i18nc("@info mimetype","Unknown");
284 case KFileItemDelegate::FriendlyMimeType
:
285 string
+= item
.isMimeTypeKnown() ? item
.mimeComment() : i18nc("@info mimetype","Unknown");
291 } // foreach (info, list)
297 // Returns the KFileItem for the index
298 KFileItem
KFileItemDelegate::Private::fileItem(const QModelIndex
&index
) const
300 const QVariant value
= index
.data(KDirModel::FileItemRole
);
301 return qvariant_cast
<KFileItem
>(value
);
305 // Replaces any newline characters in the provided string, with QChar::LineSeparator
306 QString
KFileItemDelegate::Private::replaceNewlines(const QString
&text
) const
308 QString string
= text
;
309 const QChar newline
= QLatin1Char('\n');
311 for (int i
= 0; i
< string
.length(); i
++)
312 if (string
[i
] == newline
)
313 string
[i
] = QChar::LineSeparator
;
319 // Lays the text out in a rectangle no larger than constraints, eliding it as necessary
320 QSize
KFileItemDelegate::Private::layoutText(QTextLayout
&layout
, const QStyleOptionViewItemV4
&option
,
321 const QString
&text
, const QSize
&constraints
) const
323 const QSize size
= layoutText(layout
, text
, constraints
.width());
325 if (size
.width() > constraints
.width() || size
.height() > constraints
.height())
327 const QString elided
= elidedText(layout
, option
, constraints
);
328 return layoutText(layout
, elided
, constraints
.width());
335 // Lays the text out in a rectangle no wider than maxWidth
336 QSize
KFileItemDelegate::Private::layoutText(QTextLayout
&layout
, const QString
&text
, int maxWidth
) const
338 QFontMetrics
metrics(layout
.font());
339 int leading
= metrics
.leading();
344 layout
.setText(text
);
346 layout
.beginLayout();
347 while ((line
= layout
.createLine()).isValid())
349 line
.setLineWidth(int(maxWidth
));
351 line
.setPosition(QPoint(0, height
));
352 height
+= int(line
.height());
353 widthUsed
= qMax(widthUsed
, line
.naturalTextWidth());
357 return QSize(int(widthUsed
), height
);
361 // Elides the text in the layout, by iterating over each line in the layout, eliding
362 // or word breaking the line if it's wider than the max width, and finally adding an
363 // ellipses at the end of the last line, if there are more lines than will fit within
364 // the vertical size constraints.
365 QString
KFileItemDelegate::Private::elidedText(QTextLayout
&layout
, const QStyleOptionViewItemV4
&option
,
366 const QSize
&size
) const
368 const QString text
= layout
.text();
369 int maxWidth
= size
.width();
370 int maxHeight
= size
.height();
372 bool wrapText
= (option
.features
& QStyleOptionViewItemV2::WrapText
);
374 // If the string contains a single line of text that shouldn't be word wrapped
375 if (!wrapText
&& text
.indexOf(QChar::LineSeparator
) == -1)
376 return option
.fontMetrics
.elidedText(text
, option
.textElideMode
, maxWidth
);
378 // Elide each line that has already been laid out in the layout.
380 elided
.reserve(text
.length());
382 for (int i
= 0; i
< layout
.lineCount(); i
++)
384 QTextLine line
= layout
.lineAt(i
);
385 int start
= line
.textStart();
386 int length
= line
.textLength();
388 height
+= option
.fontMetrics
.leading();
389 if (height
+ line
.height() + option
.fontMetrics
.lineSpacing() > maxHeight
)
391 // Unfortunately, if the line ends because of a line separator, elidedText() will be too
392 // clever and keep adding lines until it finds one that's too wide.
393 if (line
.naturalTextWidth() < maxWidth
&& text
[start
+ length
- 1] == QChar::LineSeparator
)
394 elided
+= text
.mid(start
, length
- 1);
396 elided
+= option
.fontMetrics
.elidedText(text
.mid(start
), option
.textElideMode
, maxWidth
);
399 else if (line
.naturalTextWidth() > maxWidth
)
401 elided
+= option
.fontMetrics
.elidedText(text
.mid(start
, length
), option
.textElideMode
, maxWidth
);
402 if (!elided
.endsWith(QChar::LineSeparator
))
403 elided
+= QChar::LineSeparator
;
406 elided
+= text
.mid(start
, length
);
408 height
+= line
.height();
415 void KFileItemDelegate::Private::setLayoutOptions(QTextLayout
&layout
, const QStyleOptionViewItemV4
&option
) const
417 QTextOption textoption
;
418 textoption
.setTextDirection(option
.direction
);
419 textoption
.setAlignment(QStyle::visualAlignment(option
.direction
, option
.displayAlignment
));
420 textoption
.setWrapMode((option
.features
& QStyleOptionViewItemV2::WrapText
) ?
421 QTextOption::WrapAtWordBoundaryOrAnywhere
: QTextOption::NoWrap
);
423 layout
.setFont(option
.font
);
424 layout
.setTextOption(textoption
);
428 QSize
KFileItemDelegate::Private::displaySizeHint(const QStyleOptionViewItemV4
&option
,
429 const QModelIndex
&index
) const
431 QString label
= option
.text
;
433 if (maximumSize
.isEmpty()) {
434 maxWidth
= verticalLayout(option
) && (option
.features
& QStyleOptionViewItemV2::WrapText
)
435 ? option
.decorationSize
.width() + 10 : 32757;
438 const Margin
&itemMargin
= activeMargins
[ItemMargin
];
439 const Margin
&textMargin
= activeMargins
[TextMargin
];
440 maxWidth
= maximumSize
.width() -
441 (itemMargin
.left
+ itemMargin
.right
) -
442 (textMargin
.left
+ textMargin
.right
);
445 KFileItem item
= fileItem(index
);
447 // To compute the nominal size for the label + info, we'll just append
448 // the information string to the label
449 const QString info
= information(option
, index
, item
);
451 label
+= QString(QChar::LineSeparator
) + info
;
454 setLayoutOptions(layout
, option
);
456 QSize size
= layoutText(layout
, label
, maxWidth
);
457 return addMargin(size
, TextMargin
);
461 QSize
KFileItemDelegate::Private::decorationSizeHint(const QStyleOptionViewItemV4
&option
,
462 const QModelIndex
&index
) const
466 QSize iconSize
= option
.icon
.actualSize(option
.decorationSize
);
467 if (!verticalLayout(option
))
468 iconSize
.rwidth() = option
.decorationSize
.width();
469 else if (iconSize
.width() < option
.decorationSize
.width())
470 iconSize
.rwidth() = qMin(iconSize
.width() + 10, option
.decorationSize
.width());
471 if (iconSize
.height() < option
.decorationSize
.height())
472 iconSize
.rheight() = option
.decorationSize
.height();
474 return addMargin(iconSize
, IconMargin
);
478 bool KFileItemDelegate::Private::verticalLayout(const QStyleOptionViewItemV4
&option
) const
480 return (option
.decorationPosition
== QStyleOptionViewItem::Top
||
481 option
.decorationPosition
== QStyleOptionViewItem::Bottom
);
485 // Converts a QVariant of type Brush or Color to a QBrush
486 QBrush
KFileItemDelegate::Private::brush(const QVariant
&value
, const QStyleOptionViewItemV4
&option
) const
488 if (value
.userType() == qMetaTypeId
<KStatefulBrush
>())
489 return qvariant_cast
<KStatefulBrush
>(value
).brush(option
.palette
);
490 switch (value
.type())
492 case QVariant::Color
:
493 return QBrush(qvariant_cast
<QColor
>(value
));
495 case QVariant::Brush
:
496 return qvariant_cast
<QBrush
>(value
);
499 return QBrush(Qt::NoBrush
);
504 QBrush
KFileItemDelegate::Private::foregroundBrush(const QStyleOptionViewItemV4
&option
, const QModelIndex
&index
) const
506 // Always use the highlight color for selected items
507 if (option
.state
& QStyle::State_Selected
)
508 return option
.palette
.brush(QPalette::HighlightedText
);
510 // If the model provides its own foreground color/brush for this item
511 const QVariant value
= index
.data(Qt::ForegroundRole
);
513 return brush(value
, option
);
515 return option
.palette
.brush(QPalette::Text
);
519 bool KFileItemDelegate::Private::isListView(const QStyleOptionViewItemV4
&option
) const
521 if (qobject_cast
<const QListView
*>(option
.widget
) || verticalLayout(option
))
528 QPixmap
KFileItemDelegate::Private::applyHoverEffect(const QPixmap
&icon
) const
530 KIconEffect
*effect
= KIconLoader::global()->iconEffect();
532 // Note that in KIconLoader terminology, active = hover.
533 // ### We're assuming that the icon group is desktop/filemanager, since this
534 // is KFileItemDelegate.
535 if (effect
->hasEffect(KIconLoader::Desktop
, KIconLoader::ActiveState
))
536 return effect
->apply(icon
, KIconLoader::Desktop
, KIconLoader::ActiveState
);
542 KIO::AnimationState
*KFileItemDelegate::Private::animationState(const QStyleOptionViewItemV4
&option
,
543 const QModelIndex
&index
,
544 const QAbstractItemView
*view
) const
546 if (!(KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects
)) {
550 if (index
.column() == KDirModel::Name
)
551 return animationHandler
->animationState(option
, index
, view
);
557 QPixmap
KFileItemDelegate::Private::transition(const QPixmap
&from
, const QPixmap
&to
, qreal amount
) const
559 int value
= int(0xff * amount
);
568 color
.setAlphaF(amount
);
570 // If the native paint engine supports Porter/Duff compositing and CompositionMode_Plus
571 if (from
.paintEngine()->hasFeature(QPaintEngine::PorterDuff
) &&
572 from
.paintEngine()->hasFeature(QPaintEngine::BlendModes
))
574 QPixmap under
= from
;
579 p
.setCompositionMode(QPainter::CompositionMode_DestinationIn
);
580 p
.fillRect(over
.rect(), color
);
584 p
.setCompositionMode(QPainter::CompositionMode_DestinationOut
);
585 p
.fillRect(under
.rect(), color
);
586 p
.setCompositionMode(QPainter::CompositionMode_Plus
);
587 p
.drawPixmap(0, 0, over
);
592 #if defined(Q_WS_X11) && defined(HAVE_XRENDER)
593 else if (from
.paintEngine()->hasFeature(QPaintEngine::PorterDuff
)) // We have Xrender support
595 // QX11PaintEngine doesn't implement CompositionMode_Plus in Qt 4.3,
596 // which we need to be able to do a transition from one pixmap to
599 // In order to avoid the overhead of converting the pixmaps to images
600 // and doing the operation entirely in software, this function has a
601 // specialized path for X11 that uses Xrender directly to do the
602 // transition. This operation can be fully accelerated in HW.
604 // This specialization can be removed when QX11PaintEngine supports
605 // CompositionMode_Plus.
606 QPixmap
source(to
), destination(from
);
609 destination
.detach();
611 Display
*dpy
= QX11Info::display();
613 XRenderPictFormat
*format
= XRenderFindStandardFormat(dpy
, PictStandardA8
);
614 XRenderPictureAttributes pa
;
615 pa
.repeat
= 1; // RepeatNormal
617 // Create a 1x1 8 bit repeating alpha picture
618 Pixmap pixmap
= XCreatePixmap(dpy
, destination
.handle(), 1, 1, 8);
619 Picture alpha
= XRenderCreatePicture(dpy
, pixmap
, format
, CPRepeat
, &pa
);
620 XFreePixmap(dpy
, pixmap
);
622 // Fill the alpha picture with the opacity value
624 xcolor
.alpha
= quint16(0xffff * amount
);
625 XRenderFillRectangle(dpy
, PictOpSrc
, alpha
, &xcolor
, 0, 0, 1, 1);
627 // Reduce the alpha of the destination with 1 - opacity
628 XRenderComposite(dpy
, PictOpOutReverse
, alpha
, None
, destination
.x11PictureHandle(),
629 0, 0, 0, 0, 0, 0, destination
.width(), destination
.height());
631 // Add source * opacity to the destination
632 XRenderComposite(dpy
, PictOpAdd
, source
.x11PictureHandle(), alpha
,
633 destination
.x11PictureHandle(),
634 0, 0, 0, 0, 0, 0, destination
.width(), destination
.height());
636 XRenderFreePicture(dpy
, alpha
);
642 // Fall back to using QRasterPaintEngine to do the transition.
643 QImage under
= from
.toImage();
644 QImage over
= to
.toImage();
648 p
.setCompositionMode(QPainter::CompositionMode_DestinationIn
);
649 p
.fillRect(over
.rect(), color
);
653 p
.setCompositionMode(QPainter::CompositionMode_DestinationOut
);
654 p
.fillRect(under
.rect(), color
);
655 p
.setCompositionMode(QPainter::CompositionMode_Plus
);
656 p
.drawImage(0, 0, over
);
659 return QPixmap::fromImage(under
);
664 void KFileItemDelegate::Private::layoutTextItems(const QStyleOptionViewItemV4
&option
, const QModelIndex
&index
,
665 QTextLayout
*labelLayout
, QTextLayout
*infoLayout
,
666 QRect
*textBoundingRect
) const
668 KFileItem item
= fileItem(index
);
669 const QString info
= information(option
, index
, item
);
670 bool showInformation
= false;
672 setLayoutOptions(*labelLayout
, option
);
674 const QRect textArea
= labelRectangle(option
);
675 QRect textRect
= subtractMargin(textArea
, Private::TextMargin
);
677 // Sizes and constraints for the different text parts
678 QSize maxLabelSize
= textRect
.size();
679 QSize maxInfoSize
= textRect
.size();
683 // If we have additional info text, and there's space for at least two lines of text,
684 // adjust the max label size to make room for at least one line of the info text
685 if (!info
.isEmpty() && textRect
.height() >= option
.fontMetrics
.lineSpacing() * 2)
687 infoLayout
->setFont(labelLayout
->font());
688 infoLayout
->setTextOption(labelLayout
->textOption());
690 maxLabelSize
.rheight() -= option
.fontMetrics
.lineSpacing();
691 showInformation
= true;
694 // Lay out the label text, and adjust the max info size based on the label size
695 labelSize
= layoutText(*labelLayout
, option
, option
.text
, maxLabelSize
);
696 maxInfoSize
.rheight() -= labelSize
.height();
698 // Lay out the info text
700 infoSize
= layoutText(*infoLayout
, option
, info
, maxInfoSize
);
702 infoSize
= QSize(0, 0);
704 // Compute the bounding rect of the text
705 const QSize
size(qMax(labelSize
.width(), infoSize
.width()), labelSize
.height() + infoSize
.height());
706 *textBoundingRect
= QStyle::alignedRect(option
.direction
, option
.displayAlignment
, size
, textRect
);
708 // Compute the positions where we should draw the layouts
709 labelLayout
->setPosition(QPointF(textRect
.x(), textBoundingRect
->y()));
710 infoLayout
->setPosition(QPointF(textRect
.x(), textBoundingRect
->y() + labelSize
.height()));
714 void KFileItemDelegate::Private::drawTextItems(QPainter
*painter
, const QTextLayout
&labelLayout
,
715 const QTextLayout
&infoLayout
, const QRect
&boundingRect
) const
717 if (shadowColor
.alpha() > 0)
719 QPixmap
pixmap(boundingRect
.size());
720 pixmap
.fill(Qt::transparent
);
723 p
.translate(-boundingRect
.topLeft());
724 p
.setPen(painter
->pen());
725 labelLayout
.draw(&p
, QPoint());
727 if (!infoLayout
.text().isEmpty())
729 QColor color
= p
.pen().color();
730 color
.setAlphaF(0.6);
733 infoLayout
.draw(&p
, QPoint());
737 int padding
= qCeil(shadowBlur
);
738 int blurFactor
= qRound(shadowBlur
);
740 QImage
image(boundingRect
.size() + QSize(padding
* 2, padding
* 2), QImage::Format_ARGB32_Premultiplied
);
743 p
.drawImage(padding
, padding
, pixmap
.toImage());
746 KIO::ImageFilter::shadowBlur(image
, blurFactor
, shadowColor
);
748 painter
->drawImage(boundingRect
.topLeft() - QPoint(padding
, padding
) + shadowOffset
.toPoint(), image
);
749 painter
->drawPixmap(boundingRect
.topLeft(), pixmap
);
753 labelLayout
.draw(painter
, QPoint());
755 if (!infoLayout
.text().isEmpty())
757 // TODO - for apps not doing funny things with the color palette,
758 // KColorScheme::InactiveText would be a much more correct choice. We
759 // should provide an API to specify what color to use for information.
760 QColor color
= painter
->pen().color();
761 color
.setAlphaF(0.6);
763 painter
->setPen(color
);
764 infoLayout
.draw(painter
, QPoint());
769 void KFileItemDelegate::Private::initStyleOption(QStyleOptionViewItemV4
*option
,
770 const QModelIndex
&index
) const
772 const KFileItem item
= fileItem(index
);
773 bool updateFontMetrics
= false;
775 // Try to get the font from the model
776 QVariant value
= index
.data(Qt::FontRole
);
777 if (value
.isValid()) {
778 option
->font
= qvariant_cast
<QFont
>(value
).resolve(option
->font
);
779 updateFontMetrics
= true;
782 // Use an italic font for symlinks
783 if (!item
.isNull() && item
.isLink()) {
784 option
->font
.setItalic(true);
785 updateFontMetrics
= true;
788 if (updateFontMetrics
)
789 option
->fontMetrics
= QFontMetrics(option
->font
);
791 // Try to get the alignment for the item from the model
792 value
= index
.data(Qt::TextAlignmentRole
);
794 option
->displayAlignment
= Qt::Alignment(value
.toInt());
796 value
= index
.data(Qt::BackgroundRole
);
798 option
->backgroundBrush
= brush(value
, *option
);
800 option
->text
= display(index
);
801 if (!option
->text
.isEmpty())
802 option
->features
|= QStyleOptionViewItemV2::HasDisplay
;
804 option
->icon
= decoration(*option
, index
);
805 if (!option
->icon
.isNull())
806 option
->features
|= QStyleOptionViewItemV2::HasDecoration
;
808 // ### Make sure this value is always true for now
809 option
->showDecorationSelected
= true;
815 // ---------------------------------------------------------------------------
820 KFileItemDelegate::KFileItemDelegate(QObject
*parent
)
821 : QAbstractItemDelegate(parent
), d(new Private(this))
823 int focusHMargin
= QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin
);
824 int focusVMargin
= QApplication::style()->pixelMetric(QStyle::PM_FocusFrameVMargin
);
826 // Margins for horizontal mode (list views, tree views, table views)
827 const int textMargin
= focusHMargin
* 4;
828 if (QApplication::isRightToLeft())
829 d
->setHorizontalMargin(Private::TextMargin
, textMargin
, focusVMargin
, focusHMargin
, focusVMargin
);
831 d
->setHorizontalMargin(Private::TextMargin
, focusHMargin
, focusVMargin
, textMargin
, focusVMargin
);
833 d
->setHorizontalMargin(Private::IconMargin
, focusHMargin
, focusVMargin
);
834 d
->setHorizontalMargin(Private::ItemMargin
, 0, 0);
836 // Margins for vertical mode (icon views)
837 d
->setVerticalMargin(Private::TextMargin
, 6, 2);
838 d
->setVerticalMargin(Private::IconMargin
, focusHMargin
, focusVMargin
);
839 d
->setVerticalMargin(Private::ItemMargin
, 0, 0);
841 setShowInformation(NoInformation
);
845 KFileItemDelegate::~KFileItemDelegate()
851 QSize
KFileItemDelegate::sizeHint(const QStyleOptionViewItem
&option
, const QModelIndex
&index
) const
853 // If the model wants to provide its own size hint for the item
854 const QVariant value
= index
.data(Qt::SizeHintRole
);
856 return qvariant_cast
<QSize
>(value
);
858 QStyleOptionViewItemV4
opt(option
);
859 d
->initStyleOption(&opt
, index
);
860 d
->setActiveMargins(d
->verticalLayout(opt
) ? Qt::Vertical
: Qt::Horizontal
);
862 const QSize displaySize
= d
->displaySizeHint(opt
, index
);
863 const QSize decorationSize
= d
->decorationSizeHint(opt
, index
);
867 if (d
->verticalLayout(opt
))
869 size
.rwidth() = qMax(displaySize
.width(), decorationSize
.width());
870 size
.rheight() = decorationSize
.height() + displaySize
.height() + 1;
874 size
.rwidth() = decorationSize
.width() + displaySize
.width() + 1;
875 size
.rheight() = qMax(decorationSize
.height(), displaySize
.height());
878 size
= d
->addMargin(size
, Private::ItemMargin
);
879 if (!d
->maximumSize
.isEmpty())
881 size
= size
.boundedTo(d
->maximumSize
);
888 QString
KFileItemDelegate::Private::display(const QModelIndex
&index
) const
890 const QVariant value
= index
.data(Qt::DisplayRole
);
892 switch (value
.type())
894 case QVariant::String
:
896 if (index
.column() == KDirModel::Size
)
897 return itemSize(index
, fileItem(index
));
899 return replaceNewlines(value
.toString());
902 case QVariant::Double
:
903 return KGlobal::locale()->formatNumber(value
.toDouble());
907 return KGlobal::locale()->formatLong(value
.toInt());
915 void KFileItemDelegate::setShowInformation(const InformationList
&list
)
917 d
->informationList
= list
;
921 void KFileItemDelegate::setShowInformation(Information value
)
923 if (value
!= NoInformation
)
924 d
->informationList
= InformationList() << value
;
926 d
->informationList
= InformationList();
930 KFileItemDelegate::InformationList
KFileItemDelegate::showInformation() const
932 return d
->informationList
;
936 void KFileItemDelegate::setShadowColor(const QColor
&color
)
938 d
->shadowColor
= color
;
942 QColor
KFileItemDelegate::shadowColor() const
944 return d
->shadowColor
;
948 void KFileItemDelegate::setShadowOffset(const QPointF
&offset
)
950 d
->shadowOffset
= offset
;
954 QPointF
KFileItemDelegate::shadowOffset() const
956 return d
->shadowOffset
;
960 void KFileItemDelegate::setShadowBlur(qreal factor
)
962 d
->shadowBlur
= factor
;
966 qreal
KFileItemDelegate::shadowBlur() const
968 return d
->shadowBlur
;
972 void KFileItemDelegate::setMaximumSize(const QSize
&size
)
974 d
->maximumSize
= size
;
978 QSize
KFileItemDelegate::maximumSize() const
980 return d
->maximumSize
;
984 void KFileItemDelegate::setShowToolTipWhenElided(bool showToolTip
)
986 d
->showToolTipWhenElided
= showToolTip
;
990 bool KFileItemDelegate::showToolTipWhenElided() const
992 return d
->showToolTipWhenElided
;
996 QIcon
KFileItemDelegate::Private::decoration(const QStyleOptionViewItemV4
&option
, const QModelIndex
&index
) const
998 const QVariant value
= index
.data(Qt::DecorationRole
);
1001 switch (value
.type())
1003 case QVariant::Icon
:
1004 icon
= qvariant_cast
<QIcon
>(value
);
1007 case QVariant::Pixmap
:
1008 icon
.addPixmap(qvariant_cast
<QPixmap
>(value
));
1011 case QVariant::Color
: {
1012 QPixmap
pixmap(option
.decorationSize
);
1013 pixmap
.fill(qvariant_cast
<QColor
>(value
));
1014 icon
.addPixmap(pixmap
);
1026 QRect
KFileItemDelegate::Private::labelRectangle(const QStyleOptionViewItemV4
&option
) const
1028 if (option
.icon
.isNull())
1029 return subtractMargin(option
.rect
, Private::ItemMargin
);
1031 const QSize decoSize
= addMargin(option
.decorationSize
, Private::IconMargin
);
1032 const QRect itemRect
= subtractMargin(option
.rect
, Private::ItemMargin
);
1033 QRect
textArea(QPoint(0, 0), itemRect
.size());
1035 switch (option
.decorationPosition
)
1037 case QStyleOptionViewItem::Top
:
1038 textArea
.setTop(decoSize
.height() + 1);
1041 case QStyleOptionViewItem::Bottom
:
1042 textArea
.setBottom(itemRect
.height() - decoSize
.height() - 1);
1045 case QStyleOptionViewItem::Left
:
1046 textArea
.setLeft(decoSize
.width() + 1);
1049 case QStyleOptionViewItem::Right
:
1050 textArea
.setRight(itemRect
.width() - decoSize
.width() - 1);
1054 textArea
.translate(itemRect
.topLeft());
1055 return QStyle::visualRect(option
.direction
, option
.rect
, textArea
);
1059 QPoint
KFileItemDelegate::Private::iconPosition(const QStyleOptionViewItemV4
&option
) const
1061 const QRect itemRect
= subtractMargin(option
.rect
, Private::ItemMargin
);
1062 Qt::Alignment alignment
;
1064 // Convert decorationPosition to the alignment the decoration will have in option.rect
1065 switch (option
.decorationPosition
)
1067 case QStyleOptionViewItem::Top
:
1068 alignment
= Qt::AlignHCenter
| Qt::AlignTop
;
1071 case QStyleOptionViewItem::Bottom
:
1072 alignment
= Qt::AlignHCenter
| Qt::AlignBottom
;
1075 case QStyleOptionViewItem::Left
:
1076 alignment
= Qt::AlignVCenter
| Qt::AlignLeft
;
1079 case QStyleOptionViewItem::Right
:
1080 alignment
= Qt::AlignVCenter
| Qt::AlignRight
;
1084 // Compute the nominal decoration rectangle
1085 const QSize size
= addMargin(option
.decorationSize
, Private::IconMargin
);
1086 const QRect rect
= QStyle::alignedRect(option
.direction
, alignment
, size
, itemRect
);
1088 // Position the icon in the center of the rectangle
1089 QRect iconRect
= QRect(QPoint(), option
.icon
.actualSize(option
.decorationSize
));
1090 iconRect
.moveCenter(rect
.center());
1092 return iconRect
.topLeft();
1096 void KFileItemDelegate::Private::drawFocusRect(QPainter
*painter
, const QStyleOptionViewItemV4
&option
,
1097 const QRect
&rect
) const
1099 if (!(option
.state
& QStyle::State_HasFocus
))
1102 QStyleOptionFocusRect opt
;
1103 opt
.direction
= option
.direction
;
1104 opt
.fontMetrics
= option
.fontMetrics
;
1105 opt
.palette
= option
.palette
;
1107 opt
.state
= option
.state
| QStyle::State_KeyboardFocusChange
| QStyle::State_Item
;
1108 opt
.backgroundColor
= option
.palette
.color(option
.state
& QStyle::State_Selected
?
1109 QPalette::Highlight
: QPalette::Base
);
1111 // Apparently some widget styles expect this hint to not be set
1112 painter
->setRenderHint(QPainter::Antialiasing
, false);
1114 QStyle
*style
= option
.widget
? option
.widget
->style() : QApplication::style();
1115 style
->drawPrimitive(QStyle::PE_FrameFocusRect
, &opt
, painter
, option
.widget
);
1117 painter
->setRenderHint(QPainter::Antialiasing
);
1121 void KFileItemDelegate::paint(QPainter
*painter
, const QStyleOptionViewItem
&option
,
1122 const QModelIndex
&index
) const
1124 if (!index
.isValid())
1127 QStyleOptionViewItemV4
opt(option
);
1128 d
->initStyleOption(&opt
, index
);
1130 // Unset the mouse over bit if we're not drawing the first column
1131 if (index
.column() > 0)
1132 opt
.state
&= ~QStyle::State_MouseOver
;
1134 opt
.viewItemPosition
= QStyleOptionViewItemV4::OnlyOne
;
1136 const QAbstractItemView
*view
= qobject_cast
<const QAbstractItemView
*>(opt
.widget
);
1139 // Check if the item is being animated
1140 // ========================================================================
1141 KIO::AnimationState
*state
= d
->animationState(opt
, index
, view
);
1142 KIO::CachedRendering
*cache
= 0;
1143 qreal progress
= ((opt
.state
& QStyle::State_MouseOver
) &&
1144 index
.column() == KDirModel::Name
) ? 1.0 : 0.0;
1148 cache
= state
->cachedRendering();
1149 progress
= state
->hoverProgress();
1151 // Clear the mouse over bit temporarily
1152 opt
.state
&= ~QStyle::State_MouseOver
;
1154 // If we have a cached rendering, draw the item from the cache
1157 if (cache
->checkValidity(opt
.state
) && cache
->regular
.size() == opt
.rect
.size())
1159 const QPixmap pixmap
= d
->transition(cache
->regular
, cache
->hover
, progress
);
1160 painter
->drawPixmap(option
.rect
.topLeft(), pixmap
);
1164 // If it wasn't valid, delete it
1165 state
->setCachedRendering(0);
1171 d
->setActiveMargins(d
->verticalLayout(opt
) ? Qt::Vertical
: Qt::Horizontal
);
1174 // Compute the metrics, and lay out the text items
1175 // ========================================================================
1176 const QPoint iconPos
= d
->iconPosition(opt
);
1177 QIcon::Mode iconMode
= option
.state
& QStyle::State_Enabled
? QIcon::Normal
: QIcon::Disabled
;
1178 QIcon::State iconState
= option
.state
& QStyle::State_Open
? QIcon::On
: QIcon::Off
;
1179 QPixmap icon
= opt
.icon
.pixmap(opt
.decorationSize
, iconMode
, iconState
);
1180 const QPen pen
= QPen(d
->foregroundBrush(opt
, index
), 0);
1182 ///### Apply the selection effect to the icon when the item is selected and
1183 // showDecorationSelected is false.
1185 QTextLayout labelLayout
, infoLayout
;
1186 QRect textBoundingRect
;
1188 d
->layoutTextItems(opt
, index
, &labelLayout
, &infoLayout
, &textBoundingRect
);
1190 QStyle
*style
= opt
.widget
? opt
.widget
->style() : QApplication::style();
1192 int focusHMargin
= style
->pixelMetric(QStyle::PM_FocusFrameHMargin
);
1193 int focusVMargin
= style
->pixelMetric(QStyle::PM_FocusFrameVMargin
);
1194 QRect focusRect
= textBoundingRect
.adjusted(-focusHMargin
, -focusVMargin
,
1195 +focusHMargin
, +focusVMargin
);
1197 // Create a new cached rendering of a hovered and an unhovered item.
1198 // We don't create a new cache for a fully hovered item, since we don't
1199 // know yet if a hover out animation will be run.
1200 // ========================================================================
1201 if (state
&& progress
< 1)
1203 cache
= new KIO::CachedRendering(opt
.state
, option
.rect
.size());
1206 p
.begin(&cache
->regular
);
1207 p
.translate(-option
.rect
.topLeft());
1208 p
.setRenderHint(QPainter::Antialiasing
);
1210 style
->drawPrimitive(QStyle::PE_PanelItemViewItem
, &opt
, &p
, opt
.widget
);
1211 p
.drawPixmap(iconPos
, icon
);
1212 d
->drawTextItems(&p
, labelLayout
, infoLayout
, textBoundingRect
);
1213 d
->drawFocusRect(&p
, opt
, focusRect
);
1216 opt
.state
|= QStyle::State_MouseOver
;
1217 icon
= d
->applyHoverEffect(icon
);
1219 p
.begin(&cache
->hover
);
1220 p
.translate(-option
.rect
.topLeft());
1221 p
.setRenderHint(QPainter::Antialiasing
);
1223 style
->drawPrimitive(QStyle::PE_PanelItemViewItem
, &opt
, &p
, opt
.widget
);
1224 p
.drawPixmap(iconPos
, icon
);
1225 d
->drawTextItems(&p
, labelLayout
, infoLayout
, textBoundingRect
);
1226 d
->drawFocusRect(&p
, opt
, focusRect
);
1229 state
->setCachedRendering(cache
);
1231 const QPixmap pixmap
= d
->transition(cache
->regular
, cache
->hover
, progress
);
1232 painter
->drawPixmap(option
.rect
.topLeft(), pixmap
);
1237 // Render the item directly if we're not using a cached rendering
1238 // ========================================================================
1240 painter
->setRenderHint(QPainter::Antialiasing
);
1241 painter
->setPen(pen
);
1243 if (progress
> 0 && !(opt
.state
& QStyle::State_MouseOver
))
1245 opt
.state
|= QStyle::State_MouseOver
;
1246 icon
= d
->applyHoverEffect(icon
);
1249 style
->drawPrimitive(QStyle::PE_PanelItemViewItem
, &opt
, painter
, opt
.widget
);
1250 painter
->drawPixmap(iconPos
, icon
);
1251 d
->drawTextItems(painter
, labelLayout
, infoLayout
, textBoundingRect
);
1252 d
->drawFocusRect(painter
, opt
, focusRect
);
1258 QWidget
*KFileItemDelegate::createEditor(QWidget
*parent
, const QStyleOptionViewItem
&option
,
1259 const QModelIndex
&index
) const
1261 QStyleOptionViewItemV4
opt(option
);
1262 d
->initStyleOption(&opt
, index
);
1264 KTextEdit
*edit
= new KTextEdit(parent
);
1265 edit
->setAcceptRichText(false);
1266 edit
->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
1267 edit
->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
1268 edit
->setAlignment(opt
.displayAlignment
);
1273 bool KFileItemDelegate::editorEvent(QEvent
*event
, QAbstractItemModel
*model
, const QStyleOptionViewItem
&option
,
1274 const QModelIndex
&index
)
1285 void KFileItemDelegate::setEditorData(QWidget
*editor
, const QModelIndex
&index
) const
1287 KTextEdit
*textedit
= qobject_cast
<KTextEdit
*>(editor
);
1288 Q_ASSERT(textedit
!= 0);
1290 const QVariant value
= index
.data(Qt::EditRole
);
1291 const QString text
= value
.toString();
1292 textedit
->insertPlainText(text
);
1293 textedit
->selectAll();
1295 const QString extension
= KMimeType::extractKnownExtension(text
);
1296 if (!extension
.isEmpty()) {
1297 // The filename contains an extension. Assure that only the filename
1299 const int selectionLength
= text
.length() - extension
.length() - 1;
1300 QTextCursor cursor
= textedit
->textCursor();
1301 cursor
.movePosition(QTextCursor::StartOfBlock
);
1302 cursor
.movePosition(QTextCursor::NextCharacter
, QTextCursor::KeepAnchor
, selectionLength
);
1303 textedit
->setTextCursor(cursor
);
1308 void KFileItemDelegate::setModelData(QWidget
*editor
, QAbstractItemModel
*model
, const QModelIndex
&index
) const
1310 KTextEdit
*textedit
= qobject_cast
<KTextEdit
*>(editor
);
1311 Q_ASSERT(textedit
!= 0);
1313 model
->setData(index
, textedit
->toPlainText(), Qt::EditRole
);
1317 void KFileItemDelegate::updateEditorGeometry(QWidget
*editor
, const QStyleOptionViewItem
&option
,
1318 const QModelIndex
&index
) const
1320 QStyleOptionViewItemV4
opt(option
);
1321 d
->initStyleOption(&opt
, index
);
1322 d
->setActiveMargins(d
->verticalLayout(opt
) ? Qt::Vertical
: Qt::Horizontal
);
1324 QRect r
= d
->labelRectangle(opt
);
1326 // Use the full available width for the editor when maximumSize is set
1327 if (d
->verticalLayout(option
) && !d
->maximumSize
.isEmpty()) {
1328 int diff
= qMax(r
.width(), d
->maximumSize
.width()) - r
.width();
1330 r
.adjust(-(diff
/ 2), 0, diff
/ 2, 0);
1333 KTextEdit
*textedit
= qobject_cast
<KTextEdit
*>(editor
);
1334 Q_ASSERT(textedit
!= 0);
1335 const int frame
= textedit
->frameWidth();
1336 r
.adjust(-frame
, -frame
, frame
, frame
);
1338 editor
->setGeometry(r
);
1342 bool KFileItemDelegate::helpEvent(QHelpEvent
*event
, QAbstractItemView
*view
, const QStyleOptionViewItem
&option
,
1343 const QModelIndex
&index
)
1348 // if the tooltip information the model keeps is different from the display information,
1350 const QVariant toolTip
= index
.data(Qt::ToolTipRole
);
1352 if (!toolTip
.isValid()) {
1356 if (index
.data() != toolTip
) {
1357 return QAbstractItemDelegate::helpEvent(event
, view
, option
, index
);
1360 if (!d
->showToolTipWhenElided
) {
1364 // in the case the tooltip information is the same as the display information,
1365 // show it only in the case the display information is elided
1366 QStyleOptionViewItemV4
opt(option
);
1367 d
->initStyleOption(&opt
, index
);
1368 d
->setActiveMargins(d
->verticalLayout(opt
) ? Qt::Vertical
: Qt::Horizontal
);
1370 QTextLayout labelLayout
;
1371 QTextLayout infoLayout
;
1372 QRect textBoundingRect
;
1373 d
->layoutTextItems(opt
, index
, &labelLayout
, &infoLayout
, &textBoundingRect
);
1374 const QString elidedText
= d
->elidedText(labelLayout
, opt
, textBoundingRect
.size());
1376 if (elidedText
!= d
->display(index
)) {
1377 return QAbstractItemDelegate::helpEvent(event
, view
, option
, index
);
1383 QRegion
KFileItemDelegate::shape(const QStyleOptionViewItem
&option
, const QModelIndex
&index
)
1385 QStyleOptionViewItemV4
opt(option
);
1386 d
->initStyleOption(&opt
, index
);
1387 d
->setActiveMargins(d
->verticalLayout(opt
) ? Qt::Vertical
: Qt::Horizontal
);
1389 QTextLayout labelLayout
;
1390 QTextLayout infoLayout
;
1391 QRect textBoundingRect
;
1392 d
->layoutTextItems(opt
, index
, &labelLayout
, &infoLayout
, &textBoundingRect
);
1394 const QPoint pos
= d
->iconPosition(opt
);
1395 QRect iconRect
= QRect(pos
, opt
.icon
.actualSize(opt
.decorationSize
));
1397 // Extend the icon rect so it touches the text rect
1398 switch (opt
.decorationPosition
)
1400 case QStyleOptionViewItem::Top
:
1401 if (iconRect
.width() < textBoundingRect
.width())
1402 iconRect
.setBottom(textBoundingRect
.top());
1404 textBoundingRect
.setTop(iconRect
.bottom());
1406 case QStyleOptionViewItem::Bottom
:
1407 if (iconRect
.width() < textBoundingRect
.width())
1408 iconRect
.setTop(textBoundingRect
.bottom());
1410 textBoundingRect
.setBottom(iconRect
.top());
1412 case QStyleOptionViewItem::Left
:
1413 iconRect
.setRight(textBoundingRect
.left());
1415 case QStyleOptionViewItem::Right
:
1416 iconRect
.setLeft(textBoundingRect
.right());
1422 region
+= textBoundingRect
;
1426 bool KFileItemDelegate::eventFilter(QObject
*object
, QEvent
*event
)
1428 KTextEdit
*editor
= qobject_cast
<KTextEdit
*>(object
);
1432 switch (event
->type())
1434 case QEvent::KeyPress
:
1436 QKeyEvent
*keyEvent
= static_cast<QKeyEvent
*>(event
);
1437 switch (keyEvent
->key())
1440 case Qt::Key_Backtab
:
1441 emit
commitData(editor
);
1442 emit
closeEditor(editor
, NoHint
);
1446 case Qt::Key_Return
:
1447 if (editor
->toPlainText().isEmpty())
1448 return true; // So a newline doesn't get inserted
1450 emit
commitData(editor
);
1451 emit
closeEditor(editor
, SubmitModelCache
);
1454 case Qt::Key_Escape
:
1455 emit
closeEditor(editor
, RevertModelCache
);
1460 } // switch (keyEvent->key())
1461 } // case QEvent::KeyPress
1463 case QEvent::FocusOut
:
1465 emit
commitData(editor
);
1466 emit
closeEditor(editor
, NoHint
);
1472 } // switch (event->type())
1476 #include "kfileitemdelegate.moc"
1479 // kate: space-indent on; indent-width 4; replace-tabs on;