1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtWidgets module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qitemdelegate.h"
41
42#include <qabstractitemmodel.h>
43#include <qapplication.h>
44#include <qbrush.h>
45#include <qpainter.h>
46#include <qpalette.h>
47#include <qpoint.h>
48#include <qrect.h>
49#include <qsize.h>
50#include <qstyle.h>
51#include <qdatetime.h>
52#include <qstyleoption.h>
53#include <qevent.h>
54#include <qpixmap.h>
55#include <qbitmap.h>
56#include <qpixmapcache.h>
57#include <qitemeditorfactory.h>
58#include <qmetaobject.h>
59#include <qtextlayout.h>
60#include <private/qabstractitemdelegate_p.h>
61#include <private/qtextengine_p.h>
62#include <qdebug.h>
63#include <qlocale.h>
64#include <qmath.h>
65
66#include <limits.h>
67
68// keep in sync with QAbstractItemDelegate::helpEvent()
69#ifndef DBL_DIG
70# define DBL_DIG 10
71#endif
72
73QT_BEGIN_NAMESPACE
74
75class QItemDelegatePrivate : public QAbstractItemDelegatePrivate
76{
77 Q_DECLARE_PUBLIC(QItemDelegate)
78
79public:
80 QItemDelegatePrivate() : f(nullptr), clipPainting(true) {}
81
82 inline const QItemEditorFactory *editorFactory() const
83 { return f ? f : QItemEditorFactory::defaultFactory(); }
84
85 inline QIcon::Mode iconMode(QStyle::State state) const
86 {
87 if (!(state & QStyle::State_Enabled)) return QIcon::Disabled;
88 if (state & QStyle::State_Selected) return QIcon::Selected;
89 return QIcon::Normal;
90 }
91
92 inline QIcon::State iconState(QStyle::State state) const
93 { return state & QStyle::State_Open ? QIcon::On : QIcon::Off; }
94
95 inline static QString replaceNewLine(QString text)
96 {
97 text.replace(before: QLatin1Char('\n'), after: QChar::LineSeparator);
98 return text;
99 }
100
101 QString valueToText(const QVariant &value, const QStyleOptionViewItem &option) const;
102
103 QItemEditorFactory *f;
104 bool clipPainting;
105
106 QRect displayRect(const QModelIndex &index, const QStyleOptionViewItem &option,
107 const QRect &decorationRect, const QRect &checkRect) const;
108 QRect textLayoutBounds(const QStyleOptionViewItem &option,
109 const QRect &decorationRect, const QRect &checkRect) const;
110 QSizeF doTextLayout(int lineWidth) const;
111 mutable QTextLayout textLayout;
112 mutable QTextOption textOption;
113
114 const QWidget *widget(const QStyleOptionViewItem &option) const
115 {
116 return option.widget;
117 }
118
119 // ### temporary hack until we have QStandardItemDelegate
120 mutable struct Icon {
121 QIcon icon;
122 QIcon::Mode mode;
123 QIcon::State state;
124 } tmp;
125};
126
127QRect QItemDelegatePrivate::displayRect(const QModelIndex &index, const QStyleOptionViewItem &option,
128 const QRect &decorationRect, const QRect &checkRect) const
129{
130 Q_Q(const QItemDelegate);
131 const QVariant value = index.data(arole: Qt::DisplayRole);
132 if (!value.isValid() || value.isNull())
133 return QRect();
134
135 const QString text = valueToText(value, option);
136 const QVariant fontVal = index.data(arole: Qt::FontRole);
137 const QFont fnt = qvariant_cast<QFont>(v: fontVal).resolve(option.font);
138 return q->textRectangle(painter: nullptr,
139 rect: textLayoutBounds(option, decorationRect, checkRect),
140 font: fnt, text);
141}
142
143// similar to QCommonStylePrivate::viewItemSize(Qt::DisplayRole)
144QRect QItemDelegatePrivate::textLayoutBounds(const QStyleOptionViewItem &option,
145 const QRect &decorationRect, const QRect &checkRect) const
146{
147 QRect rect = option.rect;
148 const QWidget *w = widget(option);
149 QStyle *style = w ? w->style() : QApplication::style();
150 const bool wrapText = option.features & QStyleOptionViewItem::WrapText;
151 // see QItemDelegate::drawDisplay
152 const int textMargin = style->pixelMetric(metric: QStyle::PM_FocusFrameHMargin, option: nullptr, widget: w) + 1;
153 switch (option.decorationPosition) {
154 case QStyleOptionViewItem::Left:
155 case QStyleOptionViewItem::Right:
156 rect.setWidth(wrapText && rect.isValid() ? rect.width() - 2 * textMargin : (QFIXED_MAX));
157 break;
158 case QStyleOptionViewItem::Top:
159 case QStyleOptionViewItem::Bottom:
160 rect.setWidth(wrapText ? option.decorationSize.width() - 2 * textMargin : (QFIXED_MAX));
161 break;
162 }
163
164 if (wrapText) {
165 if (!decorationRect.isNull())
166 rect.setWidth(rect.width() - decorationRect.width() - 2 * textMargin);
167 if (!checkRect.isNull())
168 rect.setWidth(rect.width() - checkRect.width() - 2 * textMargin);
169 // adjust height to be sure that the text fits
170 const QSizeF size = doTextLayout(lineWidth: rect.width());
171 rect.setHeight(qCeil(v: size.height()));
172 }
173
174 return rect;
175}
176
177QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const
178{
179 qreal height = 0;
180 qreal widthUsed = 0;
181 textLayout.beginLayout();
182 while (true) {
183 QTextLine line = textLayout.createLine();
184 if (!line.isValid())
185 break;
186 line.setLineWidth(lineWidth);
187 line.setPosition(QPointF(0, height));
188 height += line.height();
189 widthUsed = qMax(a: widthUsed, b: line.naturalTextWidth());
190 }
191 textLayout.endLayout();
192 return QSizeF(widthUsed, height);
193}
194
195/*!
196 \class QItemDelegate
197
198 \brief The QItemDelegate class provides display and editing facilities for
199 data items from a model.
200
201 \ingroup model-view
202 \inmodule QtWidgets
203
204 QItemDelegate can be used to provide custom display features and editor
205 widgets for item views based on QAbstractItemView subclasses. Using a
206 delegate for this purpose allows the display and editing mechanisms to be
207 customized and developed independently from the model and view.
208
209 The QItemDelegate class is one of the \l{Model/View Classes} and
210 is part of Qt's \l{Model/View Programming}{model/view framework}.
211 Note that QStyledItemDelegate has taken over the job of drawing
212 Qt's item views. We recommend the use of QStyledItemDelegate when
213 creating new delegates.
214
215 When displaying items from a custom model in a standard view, it is
216 often sufficient to simply ensure that the model returns appropriate
217 data for each of the \l{Qt::ItemDataRole}{roles} that determine the
218 appearance of items in views. The default delegate used by Qt's
219 standard views uses this role information to display items in most
220 of the common forms expected by users. However, it is sometimes
221 necessary to have even more control over the appearance of items than
222 the default delegate can provide.
223
224 This class provides default implementations of the functions for
225 painting item data in a view and editing data from item models.
226 Default implementations of the paint() and sizeHint() virtual
227 functions, defined in QAbstractItemDelegate, are provided to
228 ensure that the delegate implements the correct basic behavior
229 expected by views. You can reimplement these functions in
230 subclasses to customize the appearance of items.
231
232 When editing data in an item view, QItemDelegate provides an
233 editor widget, which is a widget that is placed on top of the view
234 while editing takes place. Editors are created with a
235 QItemEditorFactory; a default static instance provided by
236 QItemEditorFactory is installed on all item delegates. You can set
237 a custom factory using setItemEditorFactory() or set a new default
238 factory with QItemEditorFactory::setDefaultFactory(). It is the
239 data stored in the item model with the Qt::EditRole that is edited.
240
241 Only the standard editing functions for widget-based delegates are
242 reimplemented here:
243
244 \list
245 \li createEditor() returns the widget used to change data from the model
246 and can be reimplemented to customize editing behavior.
247 \li setEditorData() provides the widget with data to manipulate.
248 \li updateEditorGeometry() ensures that the editor is displayed correctly
249 with respect to the item view.
250 \li setModelData() returns updated data to the model.
251 \endlist
252
253 The closeEditor() signal indicates that the user has completed editing the data,
254 and that the editor widget can be destroyed.
255
256 \section1 Standard Roles and Data Types
257
258 The default delegate used by the standard views supplied with Qt
259 associates each standard role (defined by Qt::ItemDataRole) with certain
260 data types. Models that return data in these types can influence the
261 appearance of the delegate as described in the following table.
262
263 \table
264 \header \li Role \li Accepted Types
265 \omit
266 \row \li \l Qt::AccessibleDescriptionRole \li QString
267 \row \li \l Qt::AccessibleTextRole \li QString
268 \endomit
269 \row \li \l Qt::BackgroundRole \li QBrush (\since 4.2)
270 \row \li \l Qt::BackgroundColorRole \li QColor (obsolete; use Qt::BackgroundRole instead)
271 \row \li \l Qt::CheckStateRole \li Qt::CheckState
272 \row \li \l Qt::DecorationRole \li QIcon, QPixmap and QColor
273 \row \li \l Qt::DisplayRole \li QString and types with a string representation
274 \row \li \l Qt::EditRole \li See QItemEditorFactory for details
275 \row \li \l Qt::FontRole \li QFont
276 \row \li \l Qt::SizeHintRole \li QSize
277 \omit
278 \row \li \l Qt::StatusTipRole \li
279 \endomit
280 \row \li \l Qt::TextAlignmentRole \li Qt::Alignment
281 \row \li \l Qt::ForegroundRole \li QBrush (\since 4.2)
282 \row \li \l Qt::TextColorRole \li QColor (obsolete; use Qt::ForegroundRole instead)
283 \omit
284 \row \li \l Qt::ToolTipRole
285 \row \li \l Qt::WhatsThisRole
286 \endomit
287 \endtable
288
289 If the default delegate does not allow the level of customization that
290 you need, either for display purposes or for editing data, it is possible to
291 subclass QItemDelegate to implement the desired behavior.
292
293 \section1 Subclassing
294
295 When subclassing QItemDelegate to create a delegate that displays items
296 using a custom renderer, it is important to ensure that the delegate can
297 render items suitably for all the required states; e.g. selected,
298 disabled, checked. The documentation for the paint() function contains
299 some hints to show how this can be achieved.
300
301 You can provide custom editors by using a QItemEditorFactory. The
302 \l{Color Editor Factory Example} shows how a custom editor can be
303 made available to delegates with the default item editor
304 factory. This way, there is no need to subclass QItemDelegate. An
305 alternative is to reimplement createEditor(), setEditorData(),
306 setModelData(), and updateEditorGeometry(). This process is
307 described in the \l{Spin Box Delegate Example}.
308
309 \section1 QStyledItemDelegate vs. QItemDelegate
310
311 Since Qt 4.4, there are two delegate classes: QItemDelegate and
312 QStyledItemDelegate. However, the default delegate is QStyledItemDelegate.
313 These two classes are independent alternatives to painting and providing
314 editors for items in views. The difference between them is that
315 QStyledItemDelegate uses the current style to paint its items. We therefore
316 recommend using QStyledItemDelegate as the base class when implementing
317 custom delegates or when working with Qt style sheets. The code required
318 for either class should be equal unless the custom delegate needs to use
319 the style for drawing.
320
321 \sa {Delegate Classes}, QStyledItemDelegate, QAbstractItemDelegate,
322 {Spin Box Delegate Example}, {Settings Editor Example},
323 {Icons Example}
324*/
325
326/*!
327 Constructs an item delegate with the given \a parent.
328*/
329
330QItemDelegate::QItemDelegate(QObject *parent)
331 : QAbstractItemDelegate(*new QItemDelegatePrivate(), parent)
332{
333
334}
335
336/*!
337 Destroys the item delegate.
338*/
339
340QItemDelegate::~QItemDelegate()
341{
342}
343
344/*!
345 \property QItemDelegate::clipping
346 \brief if the delegate should clip the paint events
347 \since 4.2
348
349 This property will set the paint clip to the size of the item.
350 The default value is on. It is useful for cases such
351 as when images are larger than the size of the item.
352*/
353
354bool QItemDelegate::hasClipping() const
355{
356 Q_D(const QItemDelegate);
357 return d->clipPainting;
358}
359
360void QItemDelegate::setClipping(bool clip)
361{
362 Q_D(QItemDelegate);
363 d->clipPainting = clip;
364}
365
366QString QItemDelegatePrivate::valueToText(const QVariant &value, const QStyleOptionViewItem &option) const
367{
368 return textForRole(role: Qt::DisplayRole, value, locale: option.locale, DBL_DIG);
369}
370
371/*!
372 Renders the delegate using the given \a painter and style \a option for
373 the item specified by \a index.
374
375 When reimplementing this function in a subclass, you should update the area
376 held by the option's \l{QStyleOption::rect}{rect} variable, using the
377 option's \l{QStyleOption::state}{state} variable to determine the state of
378 the item to be displayed, and adjust the way it is painted accordingly.
379
380 For example, a selected item may need to be displayed differently to
381 unselected items, as shown in the following code:
382
383 \snippet itemviews/pixelator/pixeldelegate.cpp 2
384 \dots
385
386 After painting, you should ensure that the painter is returned to its
387 the state it was supplied in when this function was called. For example,
388 it may be useful to call QPainter::save() before painting and
389 QPainter::restore() afterwards.
390
391 \sa QStyle::State
392*/
393void QItemDelegate::paint(QPainter *painter,
394 const QStyleOptionViewItem &option,
395 const QModelIndex &index) const
396{
397 Q_D(const QItemDelegate);
398 Q_ASSERT(index.isValid());
399
400 QStyleOptionViewItem opt = setOptions(index, option);
401
402 // prepare
403 painter->save();
404 if (d->clipPainting)
405 painter->setClipRect(opt.rect);
406
407 // get the data and the rectangles
408
409 QVariant value;
410
411 QPixmap pixmap;
412 QRect decorationRect;
413 value = index.data(arole: Qt::DecorationRole);
414 if (value.isValid()) {
415 // ### we need the pixmap to call the virtual function
416 pixmap = decoration(option: opt, variant: value);
417 if (value.userType() == QMetaType::QIcon) {
418 d->tmp.icon = qvariant_cast<QIcon>(v: value);
419 d->tmp.mode = d->iconMode(state: option.state);
420 d->tmp.state = d->iconState(state: option.state);
421 const QSize size = d->tmp.icon.actualSize(size: option.decorationSize,
422 mode: d->tmp.mode, state: d->tmp.state);
423 decorationRect = QRect(QPoint(0, 0), size);
424 } else {
425 d->tmp.icon = QIcon();
426 decorationRect = QRect(QPoint(0, 0), pixmap.size());
427 }
428 } else {
429 d->tmp.icon = QIcon();
430 decorationRect = QRect();
431 }
432
433 QRect checkRect;
434 Qt::CheckState checkState = Qt::Unchecked;
435 value = index.data(arole: Qt::CheckStateRole);
436 if (value.isValid()) {
437 checkState = static_cast<Qt::CheckState>(value.toInt());
438 checkRect = doCheck(option: opt, bounding: opt.rect, variant: value);
439 }
440
441 QString text;
442 QRect displayRect;
443 value = index.data(arole: Qt::DisplayRole);
444 if (value.isValid() && !value.isNull()) {
445 text = d->valueToText(value, option: opt);
446 displayRect = d->displayRect(index, option: opt, decorationRect, checkRect);
447 }
448
449 // do the layout
450
451 doLayout(option: opt, checkRect: &checkRect, iconRect: &decorationRect, textRect: &displayRect, hint: false);
452
453 // draw the item
454
455 drawBackground(painter, option: opt, index);
456 drawCheck(painter, option: opt, rect: checkRect, state: checkState);
457 drawDecoration(painter, option: opt, rect: decorationRect, pixmap);
458 drawDisplay(painter, option: opt, rect: displayRect, text);
459 drawFocus(painter, option: opt, rect: displayRect);
460
461 // done
462 painter->restore();
463}
464
465/*!
466 Returns the size needed by the delegate to display the item
467 specified by \a index, taking into account the style information
468 provided by \a option.
469
470 When reimplementing this function, note that in case of text
471 items, QItemDelegate adds a margin (i.e. 2 *
472 QStyle::PM_FocusFrameHMargin) to the length of the text.
473*/
474
475QSize QItemDelegate::sizeHint(const QStyleOptionViewItem &option,
476 const QModelIndex &index) const
477{
478 Q_D(const QItemDelegate);
479 QVariant value = index.data(arole: Qt::SizeHintRole);
480 if (value.isValid())
481 return qvariant_cast<QSize>(v: value);
482 QRect decorationRect = rect(option, index, role: Qt::DecorationRole);
483 QRect checkRect = rect(option, index, role: Qt::CheckStateRole);
484 QRect displayRect = d->displayRect(index, option, decorationRect, checkRect);
485
486 doLayout(option, checkRect: &checkRect, iconRect: &decorationRect, textRect: &displayRect, hint: true);
487
488 return (decorationRect|displayRect|checkRect).size();
489}
490
491/*!
492 Returns the widget used to edit the item specified by \a index
493 for editing. The \a parent widget and style \a option are used to
494 control how the editor widget appears.
495
496 \sa QAbstractItemDelegate::createEditor()
497*/
498
499QWidget *QItemDelegate::createEditor(QWidget *parent,
500 const QStyleOptionViewItem &,
501 const QModelIndex &index) const
502{
503 Q_D(const QItemDelegate);
504 if (!index.isValid())
505 return nullptr;
506 const QItemEditorFactory *factory = d->f;
507 if (factory == nullptr)
508 factory = QItemEditorFactory::defaultFactory();
509 QWidget *w = factory->createEditor(userType: index.data(arole: Qt::EditRole).userType(), parent);
510 if (w)
511 w->setFocusPolicy(Qt::WheelFocus);
512 return w;
513}
514
515/*!
516 Sets the data to be displayed and edited by the \a editor from the
517 data model item specified by the model \a index.
518
519 The default implementation stores the data in the \a editor
520 widget's \l {Qt's Property System} {user property}.
521
522 \sa QMetaProperty::isUser()
523*/
524
525void QItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
526{
527#ifdef QT_NO_PROPERTIES
528 Q_UNUSED(editor);
529 Q_UNUSED(index);
530#else
531 QVariant v = index.data(arole: Qt::EditRole);
532 QByteArray n = editor->metaObject()->userProperty().name();
533
534 if (!n.isEmpty()) {
535 if (!v.isValid())
536 v = QVariant(editor->property(name: n).userType(), (const void *)nullptr);
537 editor->setProperty(name: n, value: v);
538 }
539#endif
540}
541
542/*!
543 Gets data from the \a editor widget and stores it in the specified
544 \a model at the item \a index.
545
546 The default implementation gets the value to be stored in the data
547 model from the \a editor widget's \l {Qt's Property System} {user
548 property}.
549
550 \sa QMetaProperty::isUser()
551*/
552
553void QItemDelegate::setModelData(QWidget *editor,
554 QAbstractItemModel *model,
555 const QModelIndex &index) const
556{
557#ifdef QT_NO_PROPERTIES
558 Q_UNUSED(model);
559 Q_UNUSED(editor);
560 Q_UNUSED(index);
561#else
562 Q_D(const QItemDelegate);
563 Q_ASSERT(model);
564 Q_ASSERT(editor);
565 QByteArray n = editor->metaObject()->userProperty().name();
566 if (n.isEmpty())
567 n = d->editorFactory()->valuePropertyName(
568 userType: model->data(index, role: Qt::EditRole).userType());
569 if (!n.isEmpty())
570 model->setData(index, value: editor->property(name: n), role: Qt::EditRole);
571#endif
572}
573
574/*!
575 Updates the \a editor for the item specified by \a index
576 according to the style \a option given.
577*/
578
579void QItemDelegate::updateEditorGeometry(QWidget *editor,
580 const QStyleOptionViewItem &option,
581 const QModelIndex &index) const
582{
583 if (!editor)
584 return;
585 Q_ASSERT(index.isValid());
586 QPixmap pixmap = decoration(option, variant: index.data(arole: Qt::DecorationRole));
587 QString text = QItemDelegatePrivate::replaceNewLine(text: index.data(arole: Qt::DisplayRole).toString());
588 QRect pixmapRect = QRect(QPoint(0, 0), option.decorationSize).intersected(other: pixmap.rect());
589 QRect textRect = textRectangle(painter: nullptr, rect: option.rect, font: option.font, text);
590 QRect checkRect = doCheck(option, bounding: textRect, variant: index.data(arole: Qt::CheckStateRole));
591 QStyleOptionViewItem opt = option;
592 opt.showDecorationSelected = true; // let the editor take up all available space
593 doLayout(option: opt, checkRect: &checkRect, iconRect: &pixmapRect, textRect: &textRect, hint: false);
594 editor->setGeometry(textRect);
595}
596
597/*!
598 Returns the editor factory used by the item delegate.
599 If no editor factory is set, the function will return null.
600
601 \sa setItemEditorFactory()
602*/
603QItemEditorFactory *QItemDelegate::itemEditorFactory() const
604{
605 Q_D(const QItemDelegate);
606 return d->f;
607}
608
609/*!
610 Sets the editor factory to be used by the item delegate to be the \a factory
611 specified. If no editor factory is set, the item delegate will use the
612 default editor factory.
613
614 \sa itemEditorFactory()
615*/
616void QItemDelegate::setItemEditorFactory(QItemEditorFactory *factory)
617{
618 Q_D(QItemDelegate);
619 d->f = factory;
620}
621
622/*!
623 Renders the item view \a text within the rectangle specified by \a rect
624 using the given \a painter and style \a option.
625*/
626
627void QItemDelegate::drawDisplay(QPainter *painter, const QStyleOptionViewItem &option,
628 const QRect &rect, const QString &text) const
629{
630 Q_D(const QItemDelegate);
631
632 QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
633 ? QPalette::Normal : QPalette::Disabled;
634 if (cg == QPalette::Normal && !(option.state & QStyle::State_Active))
635 cg = QPalette::Inactive;
636 if (option.state & QStyle::State_Selected) {
637 painter->fillRect(rect, option.palette.brush(cg, cr: QPalette::Highlight));
638 painter->setPen(option.palette.color(cg, cr: QPalette::HighlightedText));
639 } else {
640 painter->setPen(option.palette.color(cg, cr: QPalette::Text));
641 }
642
643 if (text.isEmpty())
644 return;
645
646 if (option.state & QStyle::State_Editing) {
647 painter->save();
648 painter->setPen(option.palette.color(cg, cr: QPalette::Text));
649 painter->drawRect(r: rect.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1));
650 painter->restore();
651 }
652
653 const QStyleOptionViewItem opt = option;
654
655 const QWidget *widget = d->widget(option);
656 QStyle *style = widget ? widget->style() : QApplication::style();
657 const int textMargin = style->pixelMetric(metric: QStyle::PM_FocusFrameHMargin, option: nullptr, widget) + 1;
658 QRect textRect = rect.adjusted(xp1: textMargin, yp1: 0, xp2: -textMargin, yp2: 0); // remove width padding
659 const bool wrapText = opt.features & QStyleOptionViewItem::WrapText;
660 d->textOption.setWrapMode(wrapText ? QTextOption::WordWrap : QTextOption::ManualWrap);
661 d->textOption.setTextDirection(option.direction);
662 d->textOption.setAlignment(QStyle::visualAlignment(direction: option.direction, alignment: option.displayAlignment));
663 d->textLayout.setTextOption(d->textOption);
664 d->textLayout.setFont(option.font);
665 d->textLayout.setText(QItemDelegatePrivate::replaceNewLine(text));
666
667 QSizeF textLayoutSize = d->doTextLayout(lineWidth: textRect.width());
668
669 if (textRect.width() < textLayoutSize.width()
670 || textRect.height() < textLayoutSize.height()) {
671 QString elided;
672 int start = 0;
673 int end = text.indexOf(c: QChar::LineSeparator, from: start);
674 if (end == -1) {
675 elided += option.fontMetrics.elidedText(text, mode: option.textElideMode, width: textRect.width());
676 } else {
677 while (end != -1) {
678 elided += option.fontMetrics.elidedText(text: text.mid(position: start, n: end - start),
679 mode: option.textElideMode, width: textRect.width());
680 elided += QChar::LineSeparator;
681 start = end + 1;
682 end = text.indexOf(c: QChar::LineSeparator, from: start);
683 }
684 //let's add the last line (after the last QChar::LineSeparator)
685 elided += option.fontMetrics.elidedText(text: text.mid(position: start),
686 mode: option.textElideMode, width: textRect.width());
687 }
688 d->textLayout.setText(elided);
689 textLayoutSize = d->doTextLayout(lineWidth: textRect.width());
690 }
691
692 const QSize layoutSize(textRect.width(), int(textLayoutSize.height()));
693 const QRect layoutRect = QStyle::alignedRect(direction: option.direction, alignment: option.displayAlignment,
694 size: layoutSize, rectangle: textRect);
695 // if we still overflow even after eliding the text, enable clipping
696 if (!hasClipping() && (textRect.width() < textLayoutSize.width()
697 || textRect.height() < textLayoutSize.height())) {
698 painter->save();
699 painter->setClipRect(layoutRect);
700 d->textLayout.draw(p: painter, pos: layoutRect.topLeft(), selections: QVector<QTextLayout::FormatRange>(), clip: layoutRect);
701 painter->restore();
702 } else {
703 d->textLayout.draw(p: painter, pos: layoutRect.topLeft(), selections: QVector<QTextLayout::FormatRange>(), clip: layoutRect);
704 }
705}
706
707/*!
708 Renders the decoration \a pixmap within the rectangle specified by
709 \a rect using the given \a painter and style \a option.
710*/
711void QItemDelegate::drawDecoration(QPainter *painter, const QStyleOptionViewItem &option,
712 const QRect &rect, const QPixmap &pixmap) const
713{
714 Q_D(const QItemDelegate);
715 // if we have an icon, we ignore the pixmap
716 if (!d->tmp.icon.isNull()) {
717 d->tmp.icon.paint(painter, rect, alignment: option.decorationAlignment,
718 mode: d->tmp.mode, state: d->tmp.state);
719 return;
720 }
721
722 if (pixmap.isNull() || !rect.isValid())
723 return;
724 QPoint p = QStyle::alignedRect(direction: option.direction, alignment: option.decorationAlignment,
725 size: pixmap.size(), rectangle: rect).topLeft();
726 if (option.state & QStyle::State_Selected) {
727 const QPixmap pm = selectedPixmap(pixmap, palette: option.palette, enabled: option.state & QStyle::State_Enabled);
728 painter->drawPixmap(p, pm);
729 } else {
730 painter->drawPixmap(p, pm: pixmap);
731 }
732}
733
734/*!
735 Renders the region within the rectangle specified by \a rect, indicating
736 that it has the focus, using the given \a painter and style \a option.
737*/
738
739void QItemDelegate::drawFocus(QPainter *painter,
740 const QStyleOptionViewItem &option,
741 const QRect &rect) const
742{
743 Q_D(const QItemDelegate);
744 if ((option.state & QStyle::State_HasFocus) == 0 || !rect.isValid())
745 return;
746 QStyleOptionFocusRect o;
747 o.QStyleOption::operator=(other: option);
748 o.rect = rect;
749 o.state |= QStyle::State_KeyboardFocusChange;
750 o.state |= QStyle::State_Item;
751 QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled)
752 ? QPalette::Normal : QPalette::Disabled;
753 o.backgroundColor = option.palette.color(cg, cr: (option.state & QStyle::State_Selected)
754 ? QPalette::Highlight : QPalette::Window);
755 const QWidget *widget = d->widget(option);
756 QStyle *style = widget ? widget->style() : QApplication::style();
757 style->drawPrimitive(pe: QStyle::PE_FrameFocusRect, opt: &o, p: painter, w: widget);
758}
759
760/*!
761 Renders a check indicator within the rectangle specified by \a
762 rect, using the given \a painter and style \a option, using the
763 given \a state.
764*/
765
766void QItemDelegate::drawCheck(QPainter *painter,
767 const QStyleOptionViewItem &option,
768 const QRect &rect, Qt::CheckState state) const
769{
770 Q_D(const QItemDelegate);
771 if (!rect.isValid())
772 return;
773
774 QStyleOptionViewItem opt(option);
775 opt.rect = rect;
776 opt.state = opt.state & ~QStyle::State_HasFocus;
777
778 switch (state) {
779 case Qt::Unchecked:
780 opt.state |= QStyle::State_Off;
781 break;
782 case Qt::PartiallyChecked:
783 opt.state |= QStyle::State_NoChange;
784 break;
785 case Qt::Checked:
786 opt.state |= QStyle::State_On;
787 break;
788 }
789
790 const QWidget *widget = d->widget(option);
791 QStyle *style = widget ? widget->style() : QApplication::style();
792 style->drawPrimitive(pe: QStyle::PE_IndicatorItemViewItemCheck, opt: &opt, p: painter, w: widget);
793}
794
795/*!
796 \since 4.2
797
798 Renders the item background for the given \a index,
799 using the given \a painter and style \a option.
800*/
801
802void QItemDelegate::drawBackground(QPainter *painter,
803 const QStyleOptionViewItem &option,
804 const QModelIndex &index) const
805{
806 if (option.showDecorationSelected && (option.state & QStyle::State_Selected)) {
807 QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
808 ? QPalette::Normal : QPalette::Disabled;
809 if (cg == QPalette::Normal && !(option.state & QStyle::State_Active))
810 cg = QPalette::Inactive;
811
812 painter->fillRect(option.rect, option.palette.brush(cg, cr: QPalette::Highlight));
813 } else {
814 QVariant value = index.data(arole: Qt::BackgroundRole);
815 if (value.canConvert<QBrush>()) {
816 QPointF oldBO = painter->brushOrigin();
817 painter->setBrushOrigin(option.rect.topLeft());
818 painter->fillRect(option.rect, qvariant_cast<QBrush>(v: value));
819 painter->setBrushOrigin(oldBO);
820 }
821 }
822}
823
824
825/*!
826 \internal
827
828 Code duplicated in QCommonStylePrivate::viewItemLayout
829*/
830
831void QItemDelegate::doLayout(const QStyleOptionViewItem &option,
832 QRect *checkRect, QRect *pixmapRect, QRect *textRect,
833 bool hint) const
834{
835 Q_ASSERT(checkRect && pixmapRect && textRect);
836 Q_D(const QItemDelegate);
837 const QWidget *widget = d->widget(option);
838 QStyle *style = widget ? widget->style() : QApplication::style();
839 const bool hasCheck = checkRect->isValid();
840 const bool hasPixmap = pixmapRect->isValid();
841 const bool hasText = textRect->isValid();
842 const bool hasMargin = (hasText | hasPixmap | hasCheck);
843 const int frameHMargin = hasMargin ?
844 style->pixelMetric(metric: QStyle::PM_FocusFrameHMargin, option: nullptr, widget) + 1 : 0;
845 const int textMargin = hasText ? frameHMargin : 0;
846 const int pixmapMargin = hasPixmap ? frameHMargin : 0;
847 const int checkMargin = hasCheck ? frameHMargin : 0;
848 const int x = option.rect.left();
849 const int y = option.rect.top();
850 int w, h;
851
852 textRect->adjust(dx1: -textMargin, dy1: 0, dx2: textMargin, dy2: 0); // add width padding
853 if (textRect->height() == 0 && (!hasPixmap || !hint)) {
854 //if there is no text, we still want to have a decent height for the item sizeHint and the editor size
855 textRect->setHeight(option.fontMetrics.height());
856 }
857
858 QSize pm(0, 0);
859 if (hasPixmap) {
860 pm = pixmapRect->size();
861 pm.rwidth() += 2 * pixmapMargin;
862 }
863 if (hint) {
864 h = qMax(a: checkRect->height(), b: qMax(a: textRect->height(), b: pm.height()));
865 if (option.decorationPosition == QStyleOptionViewItem::Left
866 || option.decorationPosition == QStyleOptionViewItem::Right) {
867 w = textRect->width() + pm.width();
868 } else {
869 w = qMax(a: textRect->width(), b: pm.width());
870 }
871 } else {
872 w = option.rect.width();
873 h = option.rect.height();
874 }
875
876 int cw = 0;
877 QRect check;
878 if (hasCheck) {
879 cw = checkRect->width() + 2 * checkMargin;
880 if (hint) w += cw;
881 if (option.direction == Qt::RightToLeft) {
882 check.setRect(ax: x + w - cw, ay: y, aw: cw, ah: h);
883 } else {
884 check.setRect(ax: x, ay: y, aw: cw, ah: h);
885 }
886 }
887
888 // at this point w should be the *total* width
889
890 QRect display;
891 QRect decoration;
892 switch (option.decorationPosition) {
893 case QStyleOptionViewItem::Top: {
894 if (hasPixmap)
895 pm.setHeight(pm.height() + pixmapMargin); // add space
896 h = hint ? textRect->height() : h - pm.height();
897
898 if (option.direction == Qt::RightToLeft) {
899 decoration.setRect(ax: x, ay: y, aw: w - cw, ah: pm.height());
900 display.setRect(ax: x, ay: y + pm.height(), aw: w - cw, ah: h);
901 } else {
902 decoration.setRect(ax: x + cw, ay: y, aw: w - cw, ah: pm.height());
903 display.setRect(ax: x + cw, ay: y + pm.height(), aw: w - cw, ah: h);
904 }
905 break; }
906 case QStyleOptionViewItem::Bottom: {
907 if (hasText)
908 textRect->setHeight(textRect->height() + textMargin); // add space
909 h = hint ? textRect->height() + pm.height() : h;
910
911 if (option.direction == Qt::RightToLeft) {
912 display.setRect(ax: x, ay: y, aw: w - cw, ah: textRect->height());
913 decoration.setRect(ax: x, ay: y + textRect->height(), aw: w - cw, ah: h - textRect->height());
914 } else {
915 display.setRect(ax: x + cw, ay: y, aw: w - cw, ah: textRect->height());
916 decoration.setRect(ax: x + cw, ay: y + textRect->height(), aw: w - cw, ah: h - textRect->height());
917 }
918 break; }
919 case QStyleOptionViewItem::Left: {
920 if (option.direction == Qt::LeftToRight) {
921 decoration.setRect(ax: x + cw, ay: y, aw: pm.width(), ah: h);
922 display.setRect(ax: decoration.right() + 1, ay: y, aw: w - pm.width() - cw, ah: h);
923 } else {
924 display.setRect(ax: x, ay: y, aw: w - pm.width() - cw, ah: h);
925 decoration.setRect(ax: display.right() + 1, ay: y, aw: pm.width(), ah: h);
926 }
927 break; }
928 case QStyleOptionViewItem::Right: {
929 if (option.direction == Qt::LeftToRight) {
930 display.setRect(ax: x + cw, ay: y, aw: w - pm.width() - cw, ah: h);
931 decoration.setRect(ax: display.right() + 1, ay: y, aw: pm.width(), ah: h);
932 } else {
933 decoration.setRect(ax: x, ay: y, aw: pm.width(), ah: h);
934 display.setRect(ax: decoration.right() + 1, ay: y, aw: w - pm.width() - cw, ah: h);
935 }
936 break; }
937 default:
938 qWarning(msg: "doLayout: decoration position is invalid");
939 decoration = *pixmapRect;
940 break;
941 }
942
943 if (!hint) { // we only need to do the internal layout if we are going to paint
944 *checkRect = QStyle::alignedRect(direction: option.direction, alignment: Qt::AlignCenter,
945 size: checkRect->size(), rectangle: check);
946 *pixmapRect = QStyle::alignedRect(direction: option.direction, alignment: option.decorationAlignment,
947 size: pixmapRect->size(), rectangle: decoration);
948 // the text takes up all available space, unless the decoration is not shown as selected
949 if (option.showDecorationSelected)
950 *textRect = display;
951 else
952 *textRect = QStyle::alignedRect(direction: option.direction, alignment: option.displayAlignment,
953 size: textRect->size().boundedTo(otherSize: display.size()), rectangle: display);
954 } else {
955 *checkRect = check;
956 *pixmapRect = decoration;
957 *textRect = display;
958 }
959}
960
961/*!
962 \internal
963
964 Returns the pixmap used to decorate the root of the item view.
965 The style \a option controls the appearance of the root; the \a variant
966 refers to the data associated with an item.
967*/
968
969QPixmap QItemDelegate::decoration(const QStyleOptionViewItem &option, const QVariant &variant) const
970{
971 Q_D(const QItemDelegate);
972 switch (variant.userType()) {
973 case QMetaType::QIcon: {
974 QIcon::Mode mode = d->iconMode(state: option.state);
975 QIcon::State state = d->iconState(state: option.state);
976 return qvariant_cast<QIcon>(v: variant).pixmap(size: option.decorationSize, mode, state); }
977 case QMetaType::QColor: {
978 static QPixmap pixmap(option.decorationSize);
979 pixmap.fill(fillColor: qvariant_cast<QColor>(v: variant));
980 return pixmap; }
981 default:
982 break;
983 }
984
985 return qvariant_cast<QPixmap>(v: variant);
986}
987
988// hacky but faster version of "QString::asprintf("%d-%d", i, enabled)"
989static QString qPixmapSerial(quint64 i, bool enabled)
990{
991 ushort arr[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', ushort('0' + enabled) };
992 ushort *ptr = &arr[16];
993
994 while (i > 0) {
995 // hey - it's our internal representation, so use the ascii character after '9'
996 // instead of 'a' for hex
997 *(--ptr) = '0' + i % 16;
998 i >>= 4;
999 }
1000
1001 return QString((const QChar *)ptr, int(&arr[sizeof(arr) / sizeof(ushort)] - ptr));
1002}
1003
1004#if QT_DEPRECATED_SINCE(5, 13)
1005QPixmap *QItemDelegate::selected(const QPixmap &pixmap, const QPalette &palette, bool enabled) const
1006{
1007 const QString key = qPixmapSerial(i: pixmap.cacheKey(), enabled);
1008QT_WARNING_PUSH
1009QT_WARNING_DISABLE_DEPRECATED
1010 QPixmap *pm = QPixmapCache::find(key);
1011 if (pm)
1012 return pm;
1013 selectedPixmap(pixmap, palette, enabled);
1014 return QPixmapCache::find(key);
1015QT_WARNING_POP
1016}
1017#endif
1018
1019/*!
1020 \internal
1021 Returns the selected version of the given \a pixmap using the given \a palette.
1022 The \a enabled argument decides whether the normal or disabled highlight color of
1023 the palette is used.
1024*/
1025QPixmap QItemDelegate::selectedPixmap(const QPixmap &pixmap, const QPalette &palette, bool enabled)
1026{
1027 const QString key = qPixmapSerial(i: pixmap.cacheKey(), enabled);
1028 QPixmap pm;
1029 if (!QPixmapCache::find(key, pixmap: &pm)) {
1030 QImage img = pixmap.toImage().convertToFormat(f: QImage::Format_ARGB32_Premultiplied);
1031
1032 QColor color = palette.color(cg: enabled ? QPalette::Normal : QPalette::Disabled,
1033 cr: QPalette::Highlight);
1034 color.setAlphaF((qreal)0.3);
1035
1036 QPainter painter(&img);
1037 painter.setCompositionMode(QPainter::CompositionMode_SourceAtop);
1038 painter.fillRect(x: 0, y: 0, w: img.width(), h: img.height(), b: color);
1039 painter.end();
1040
1041 pm = QPixmap(QPixmap::fromImage(image: img));
1042 const int n = (img.sizeInBytes() >> 10) + 1;
1043 if (QPixmapCache::cacheLimit() < n)
1044 QPixmapCache::setCacheLimit(n);
1045
1046 QPixmapCache::insert(key, pixmap: pm);
1047 }
1048 return pm;
1049}
1050
1051/*!
1052 \internal
1053 Only used (and usable) for Qt::DecorationRole and Qt::CheckStateRole
1054*/
1055QRect QItemDelegate::rect(const QStyleOptionViewItem &option,
1056 const QModelIndex &index, int role) const
1057{
1058 Q_D(const QItemDelegate);
1059 QVariant value = index.data(arole: role);
1060 if (role == Qt::CheckStateRole)
1061 return doCheck(option, bounding: option.rect, variant: value);
1062 if (value.isValid() && !value.isNull()) {
1063 switch (value.userType()) {
1064 case QMetaType::UnknownType:
1065 break;
1066 case QMetaType::QPixmap: {
1067 const QPixmap &pixmap = qvariant_cast<QPixmap>(v: value);
1068 return QRect(QPoint(0, 0), pixmap.size() / pixmap.devicePixelRatio() ); }
1069 case QMetaType::QImage: {
1070 const QImage &image = qvariant_cast<QImage>(v: value);
1071 return QRect(QPoint(0, 0), image.size() / image.devicePixelRatio() ); }
1072 case QMetaType::QIcon: {
1073 QIcon::Mode mode = d->iconMode(state: option.state);
1074 QIcon::State state = d->iconState(state: option.state);
1075 QIcon icon = qvariant_cast<QIcon>(v: value);
1076 QSize size = icon.actualSize(size: option.decorationSize, mode, state);
1077 return QRect(QPoint(0, 0), size); }
1078 case QMetaType::QColor:
1079 return QRect(QPoint(0, 0), option.decorationSize);
1080 case QMetaType::QString:
1081 default: {
1082 const QString text = d->valueToText(value, option);
1083 value = index.data(arole: Qt::FontRole);
1084 QFont fnt = qvariant_cast<QFont>(v: value).resolve(option.font);
1085 return textRectangle(painter: nullptr,
1086 rect: d->textLayoutBounds(option, decorationRect: QRect(), checkRect: QRect()),
1087 font: fnt, text); }
1088 }
1089 }
1090 return QRect();
1091}
1092
1093/*!
1094 \internal
1095*/
1096QRect QItemDelegate::doCheck(const QStyleOptionViewItem &option,
1097 const QRect &bounding, const QVariant &value) const
1098{
1099 if (value.isValid()) {
1100 Q_D(const QItemDelegate);
1101 QStyleOptionButton opt;
1102 opt.QStyleOption::operator=(other: option);
1103 opt.rect = bounding;
1104 const QWidget *widget = d->widget(option); // cast
1105 QStyle *style = widget ? widget->style() : QApplication::style();
1106 return style->subElementRect(subElement: QStyle::SE_ItemViewItemCheckIndicator, option: &opt, widget);
1107 }
1108 return QRect();
1109}
1110
1111/*!
1112 \internal
1113*/
1114QRect QItemDelegate::textRectangle(QPainter * /*painter*/, const QRect &rect,
1115 const QFont &font, const QString &text) const
1116{
1117 Q_D(const QItemDelegate);
1118 d->textOption.setWrapMode(QTextOption::WordWrap);
1119 d->textLayout.setTextOption(d->textOption);
1120 d->textLayout.setFont(font);
1121 d->textLayout.setText(QItemDelegatePrivate::replaceNewLine(text));
1122 QSizeF fpSize = d->doTextLayout(lineWidth: rect.width());
1123 const QSize size = QSize(qCeil(v: fpSize.width()), qCeil(v: fpSize.height()));
1124 // ###: textRectangle should take style option as argument
1125 const int textMargin = QApplication::style()->pixelMetric(metric: QStyle::PM_FocusFrameHMargin, option: nullptr) + 1;
1126 return QRect(0, 0, size.width() + 2 * textMargin, size.height());
1127}
1128
1129/*!
1130 \fn bool QItemDelegate::eventFilter(QObject *editor, QEvent *event)
1131
1132 Returns \c true if the given \a editor is a valid QWidget and the
1133 given \a event is handled; otherwise returns \c false. The following
1134 key press events are handled by default:
1135
1136 \list
1137 \li \uicontrol Tab
1138 \li \uicontrol Backtab
1139 \li \uicontrol Enter
1140 \li \uicontrol Return
1141 \li \uicontrol Esc
1142 \endlist
1143
1144 In the case of \uicontrol Tab, \uicontrol Backtab, \uicontrol Enter and \uicontrol Return
1145 key press events, the \a editor's data is committed to the model
1146 and the editor is closed. If the \a event is a \uicontrol Tab key press
1147 the view will open an editor on the next item in the
1148 view. Likewise, if the \a event is a \uicontrol Backtab key press the
1149 view will open an editor on the \e previous item in the view.
1150
1151 If the event is a \uicontrol Esc key press event, the \a editor is
1152 closed \e without committing its data.
1153
1154 \sa commitData(), closeEditor()
1155*/
1156
1157bool QItemDelegate::eventFilter(QObject *object, QEvent *event)
1158{
1159 Q_D(QItemDelegate);
1160 return d->editorEventFilter(object, event);
1161}
1162
1163/*!
1164 \reimp
1165*/
1166
1167bool QItemDelegate::editorEvent(QEvent *event,
1168 QAbstractItemModel *model,
1169 const QStyleOptionViewItem &option,
1170 const QModelIndex &index)
1171{
1172 Q_ASSERT(event);
1173 Q_ASSERT(model);
1174
1175 // make sure that the item is checkable
1176 Qt::ItemFlags flags = model->flags(index);
1177 if (!(flags & Qt::ItemIsUserCheckable) || !(option.state & QStyle::State_Enabled)
1178 || !(flags & Qt::ItemIsEnabled))
1179 return false;
1180
1181 // make sure that we have a check state
1182 QVariant value = index.data(arole: Qt::CheckStateRole);
1183 if (!value.isValid())
1184 return false;
1185
1186 // make sure that we have the right event type
1187 if ((event->type() == QEvent::MouseButtonRelease)
1188 || (event->type() == QEvent::MouseButtonDblClick)
1189 || (event->type() == QEvent::MouseButtonPress)) {
1190 QRect checkRect = doCheck(option, bounding: option.rect, value: Qt::Checked);
1191 QRect emptyRect;
1192 doLayout(option, checkRect: &checkRect, pixmapRect: &emptyRect, textRect: &emptyRect, hint: false);
1193 QMouseEvent *me = static_cast<QMouseEvent*>(event);
1194 if (me->button() != Qt::LeftButton || !checkRect.contains(p: me->pos()))
1195 return false;
1196
1197 // eat the double click events inside the check rect
1198 if ((event->type() == QEvent::MouseButtonPress)
1199 || (event->type() == QEvent::MouseButtonDblClick))
1200 return true;
1201
1202 } else if (event->type() == QEvent::KeyPress) {
1203 if (static_cast<QKeyEvent*>(event)->key() != Qt::Key_Space
1204 && static_cast<QKeyEvent*>(event)->key() != Qt::Key_Select)
1205 return false;
1206 } else {
1207 return false;
1208 }
1209
1210 Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
1211 if (flags & Qt::ItemIsUserTristate)
1212 state = ((Qt::CheckState)((state + 1) % 3));
1213 else
1214 state = (state == Qt::Checked) ? Qt::Unchecked : Qt::Checked;
1215 return model->setData(index, value: state, role: Qt::CheckStateRole);
1216}
1217
1218/*!
1219 \internal
1220*/
1221
1222QStyleOptionViewItem QItemDelegate::setOptions(const QModelIndex &index,
1223 const QStyleOptionViewItem &option) const
1224{
1225 QStyleOptionViewItem opt = option;
1226
1227 // set font
1228 QVariant value = index.data(arole: Qt::FontRole);
1229 if (value.isValid()){
1230 opt.font = qvariant_cast<QFont>(v: value).resolve(opt.font);
1231 opt.fontMetrics = QFontMetrics(opt.font);
1232 }
1233
1234 // set text alignment
1235 value = index.data(arole: Qt::TextAlignmentRole);
1236 if (value.isValid())
1237 opt.displayAlignment = Qt::Alignment(value.toInt());
1238
1239 // set foreground brush
1240 value = index.data(arole: Qt::ForegroundRole);
1241 if (value.canConvert<QBrush>())
1242 opt.palette.setBrush(acr: QPalette::Text, abrush: qvariant_cast<QBrush>(v: value));
1243
1244 // disable style animations for checkboxes etc. within itemviews (QTBUG-30146)
1245 opt.styleObject = nullptr;
1246
1247 return opt;
1248}
1249
1250QT_END_NAMESPACE
1251
1252#include "moc_qitemdelegate.cpp"
1253

source code of qtbase/src/widgets/itemviews/qitemdelegate.cpp