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