source: trunk/src/gui/itemviews/qitemdelegate.cpp@ 642

Last change on this file since 642 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 48.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
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
73#include <limits.h>
74
75#ifndef DBL_DIG
76# define DBL_DIG 10
77#endif
78
79QT_BEGIN_NAMESPACE
80
81class QItemDelegatePrivate : public QObjectPrivate
82{
83 Q_DECLARE_PUBLIC(QItemDelegate)
84
85public:
86 QItemDelegatePrivate() : f(0), clipPainting(true) {}
87
88 inline const QItemEditorFactory *editorFactory() const
89 { return f ? f : QItemEditorFactory::defaultFactory(); }
90
91 inline QIcon::Mode iconMode(QStyle::State state) const
92 {
93 if (!(state & QStyle::State_Enabled)) return QIcon::Disabled;
94 if (state & QStyle::State_Selected) return QIcon::Selected;
95 return QIcon::Normal;
96 }
97
98 inline QIcon::State iconState(QStyle::State state) const
99 { return state & QStyle::State_Open ? QIcon::On : QIcon::Off; }
100
101 inline static QString replaceNewLine(QString text)
102 {
103 const QChar nl = QLatin1Char('\n');
104 for (int i = 0; i < text.count(); ++i)
105 if (text.at(i) == nl)
106 text[i] = QChar::LineSeparator;
107 return text;
108 }
109
110 static QString valueToText(const QVariant &value, const QStyleOptionViewItemV4 &option);
111
112 void _q_commitDataAndCloseEditor(QWidget *editor);
113
114 QItemEditorFactory *f;
115 bool clipPainting;
116
117 QRect textLayoutBounds(const QStyleOptionViewItemV2 &options) const;
118 QSizeF doTextLayout(int lineWidth) const;
119 mutable QTextLayout textLayout;
120 mutable QTextOption textOption;
121
122 const QWidget *widget(const QStyleOptionViewItem &option) const
123 {
124 if (const QStyleOptionViewItemV3 *v3 = qstyleoption_cast<const QStyleOptionViewItemV3 *>(&option))
125 return v3->widget;
126
127 return 0;
128 }
129
130 // ### temporary hack until we have QStandardItemDelegate
131 mutable struct Icon {
132 QIcon icon;
133 QIcon::Mode mode;
134 QIcon::State state;
135 } tmp;
136};
137
138void QItemDelegatePrivate::_q_commitDataAndCloseEditor(QWidget *editor)
139{
140 Q_Q(QItemDelegate);
141 emit q->commitData(editor);
142 emit q->closeEditor(editor, QAbstractItemDelegate::SubmitModelCache);
143}
144
145QRect QItemDelegatePrivate::textLayoutBounds(const QStyleOptionViewItemV2 &option) const
146{
147 QRect rect = option.rect;
148 const bool wrapText = option.features & QStyleOptionViewItemV2::WrapText;
149 switch (option.decorationPosition) {
150 case QStyleOptionViewItem::Left:
151 case QStyleOptionViewItem::Right:
152 rect.setWidth(wrapText && rect.isValid() ? rect.width() : (QFIXED_MAX));
153 break;
154 case QStyleOptionViewItem::Top:
155 case QStyleOptionViewItem::Bottom:
156 rect.setWidth(wrapText ? option.decorationSize.width() : (QFIXED_MAX));
157 break;
158 }
159
160 return rect;
161}
162
163QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const
164{
165 qreal height = 0;
166 qreal widthUsed = 0;
167 textLayout.beginLayout();
168 while (true) {
169 QTextLine line = textLayout.createLine();
170 if (!line.isValid())
171 break;
172 line.setLineWidth(lineWidth);
173 line.setPosition(QPointF(0, height));
174 height += line.height();
175 widthUsed = qMax(widthUsed, line.naturalTextWidth());
176 }
177 textLayout.endLayout();
178 return QSizeF(widthUsed, height);
179}
180
181/*!
182 \class QItemDelegate
183
184 \brief The QItemDelegate class provides display and editing facilities for
185 data items from a model.
186
187 \ingroup model-view
188
189
190 QItemDelegate can be used to provide custom display features and editor
191 widgets for item views based on QAbstractItemView subclasses. Using a
192 delegate for this purpose allows the display and editing mechanisms to be
193 customized and developed independently from the model and view.
194
195 The QItemDelegate class is one of the \l{Model/View Classes} and
196 is part of Qt's \l{Model/View Programming}{model/view framework}.
197 Note that QStyledItemDelegate has taken over the job of drawing
198 Qt's item views. We recommend the use of QStyledItemDelegate when
199 creating new delegates.
200
201 When displaying items from a custom model in a standard view, it is
202 often sufficient to simply ensure that the model returns appropriate
203 data for each of the \l{Qt::ItemDataRole}{roles} that determine the
204 appearance of items in views. The default delegate used by Qt's
205 standard views uses this role information to display items in most
206 of the common forms expected by users. However, it is sometimes
207 necessary to have even more control over the appearance of items than
208 the default delegate can provide.
209
210 This class provides default implementations of the functions for
211 painting item data in a view and editing data from item models.
212 Default implementations of the paint() and sizeHint() virtual
213 functions, defined in QAbstractItemDelegate, are provided to
214 ensure that the delegate implements the correct basic behavior
215 expected by views. You can reimplement these functions in
216 subclasses to customize the appearance of items.
217
218 When editing data in an item view, QItemDelegate provides an
219 editor widget, which is a widget that is placed on top of the view
220 while editing takes place. Editors are created with a
221 QItemEditorFactory; a default static instance provided by
222 QItemEditorFactory is installed on all item delegates. You can set
223 a custom factory using setItemEditorFactory() or set a new default
224 factory with QItemEditorFactory::setDefaultFactory(). It is the
225 data stored in the item model with the Qt::EditRole that is edited.
226
227 Only the standard editing functions for widget-based delegates are
228 reimplemented here:
229
230 \list
231 \o createEditor() returns the widget used to change data from the model
232 and can be reimplemented to customize editing behavior.
233 \o setEditorData() provides the widget with data to manipulate.
234 \o updateEditorGeometry() ensures that the editor is displayed correctly
235 with respect to the item view.
236 \o setModelData() returns updated data to the model.
237 \endlist
238
239 The closeEditor() signal indicates that the user has completed editing the data,
240 and that the editor widget can be destroyed.
241
242 \section1 Standard Roles and Data Types
243
244 The default delegate used by the standard views supplied with Qt
245 associates each standard role (defined by Qt::ItemDataRole) with certain
246 data types. Models that return data in these types can influence the
247 appearance of the delegate as described in the following table.
248
249 \table
250 \header \o Role \o Accepted Types
251 \omit
252 \row \o \l Qt::AccessibleDescriptionRole \o QString
253 \row \o \l Qt::AccessibleTextRole \o QString
254 \endomit
255 \row \o \l Qt::BackgroundRole \o QBrush
256 \row \o \l Qt::BackgroundColorRole \o QColor (obsolete; use Qt::BackgroundRole instead)
257 \row \o \l Qt::CheckStateRole \o Qt::CheckState
258 \row \o \l Qt::DecorationRole \o QIcon, QPixmap and QColor
259 \row \o \l Qt::DisplayRole \o QString and types with a string representation
260 \row \o \l Qt::EditRole \o See QItemEditorFactory for details
261 \row \o \l Qt::FontRole \o QFont
262 \row \o \l Qt::SizeHintRole \o QSize
263 \omit
264 \row \o \l Qt::StatusTipRole \o
265 \endomit
266 \row \o \l Qt::TextAlignmentRole \o Qt::Alignment
267 \row \o \l Qt::ForegroundRole \o QBrush
268 \row \o \l Qt::TextColorRole \o QColor (obsolete; use Qt::ForegroundRole instead)
269 \omit
270 \row \o \l Qt::ToolTipRole
271 \row \o \l Qt::WhatsThisRole
272 \endomit
273 \endtable
274
275 If the default delegate does not allow the level of customization that
276 you need, either for display purposes or for editing data, it is possible to
277 subclass QItemDelegate to implement the desired behavior.
278
279 \section1 Subclassing
280
281 When subclassing QItemDelegate to create a delegate that displays items
282 using a custom renderer, it is important to ensure that the delegate can
283 render items suitably for all the required states; e.g. selected,
284 disabled, checked. The documentation for the paint() function contains
285 some hints to show how this can be achieved.
286
287 You can provide custom editors by using a QItemEditorFactory. The
288 \l{Color Editor Factory Example} shows how a custom editor can be
289 made available to delegates with the default item editor
290 factory. This way, there is no need to subclass QItemDelegate. An
291 alternative is to reimplement createEditor(), setEditorData(),
292 setModelData(), and updateEditorGeometry(). This process is
293 described in the \l{Spin Box Delegate Example}.
294
295 \section1 QStyledItemDelegate vs. QItemDelegate
296
297 Since Qt 4.4, there are two delegate classes: QItemDelegate and
298 QStyledItemDelegate. However, the default delegate is QStyledItemDelegate.
299 These two classes are independent alternatives to painting and providing
300 editors for items in views. The difference between them is that
301 QStyledItemDelegate uses the current style to paint its items. We therefore
302 recommend using QStyledItemDelegate as the base class when implementing
303 custom delegates or when working with Qt style sheets. The code required
304 for either class should be equal unless the custom delegate needs to use
305 the style for drawing.
306
307 \sa {Delegate Classes}, QStyledItemDelegate, QAbstractItemDelegate,
308 {Spin Box Delegate Example}, {Settings Editor Example},
309 {Icons Example}
310*/
311
312/*!
313 Constructs an item delegate with the given \a parent.
314*/
315
316QItemDelegate::QItemDelegate(QObject *parent)
317 : QAbstractItemDelegate(*new QItemDelegatePrivate(), parent)
318{
319
320}
321
322/*!
323 Destroys the item delegate.
324*/
325
326QItemDelegate::~QItemDelegate()
327{
328}
329
330/*!
331 \property QItemDelegate::clipping
332 \brief if the delegate should clip the paint events
333 \since 4.2
334
335 This property will set the paint clip to the size of the item.
336 The default value is on. It is useful for cases such
337 as when images are larger than the size of the item.
338*/
339
340bool QItemDelegate::hasClipping() const
341{
342 Q_D(const QItemDelegate);
343 return d->clipPainting;
344}
345
346void QItemDelegate::setClipping(bool clip)
347{
348 Q_D(QItemDelegate);
349 d->clipPainting = clip;
350}
351
352QString QItemDelegatePrivate::valueToText(const QVariant &value, const QStyleOptionViewItemV4 &option)
353{
354 QString text;
355 switch (value.userType()) {
356 case QMetaType::Float:
357 text = option.locale.toString(value.toFloat(), 'g');
358 break;
359 case QVariant::Double:
360 text = option.locale.toString(value.toDouble(), 'g', DBL_DIG);
361 break;
362 case QVariant::Int:
363 case QVariant::LongLong:
364 text = option.locale.toString(value.toLongLong());
365 break;
366 case QVariant::UInt:
367 case QVariant::ULongLong:
368 text = option.locale.toString(value.toULongLong());
369 break;
370 case QVariant::Date:
371 text = option.locale.toString(value.toDate(), QLocale::ShortFormat);
372 break;
373 case QVariant::Time:
374 text = option.locale.toString(value.toTime(), QLocale::ShortFormat);
375 break;
376 case QVariant::DateTime:
377 text = option.locale.toString(value.toDateTime().date(), QLocale::ShortFormat);
378 text += QLatin1Char(' ');
379 text += option.locale.toString(value.toDateTime().time(), QLocale::ShortFormat);
380 break;
381 default:
382 text = replaceNewLine(value.toString());
383 break;
384 }
385 return text;
386}
387
388/*!
389 Renders the delegate using the given \a painter and style \a option for
390 the item specified by \a index.
391
392 When reimplementing this function in a subclass, you should update the area
393 held by the option's \l{QStyleOption::rect}{rect} variable, using the
394 option's \l{QStyleOption::state}{state} variable to determine the state of
395 the item to be displayed, and adjust the way it is painted accordingly.
396
397 For example, a selected item may need to be displayed differently to
398 unselected items, as shown in the following code:
399
400 \snippet examples/itemviews/pixelator/pixeldelegate.cpp 2
401 \dots
402
403 After painting, you should ensure that the painter is returned to its
404 the state it was supplied in when this function was called. For example,
405 it may be useful to call QPainter::save() before painting and
406 QPainter::restore() afterwards.
407
408 \sa QStyle::State
409*/
410void QItemDelegate::paint(QPainter *painter,
411 const QStyleOptionViewItem &option,
412 const QModelIndex &index) const
413{
414 Q_D(const QItemDelegate);
415 Q_ASSERT(index.isValid());
416
417 QStyleOptionViewItemV4 opt = setOptions(index, option);
418
419 const QStyleOptionViewItemV2 *v2 = qstyleoption_cast<const QStyleOptionViewItemV2 *>(&option);
420 opt.features = v2 ? v2->features
421 : QStyleOptionViewItemV2::ViewItemFeatures(QStyleOptionViewItemV2::None);
422 const QStyleOptionViewItemV3 *v3 = qstyleoption_cast<const QStyleOptionViewItemV3 *>(&option);
423 opt.locale = v3 ? v3->locale : QLocale();
424 opt.widget = v3 ? v3->widget : 0;
425
426 // prepare
427 painter->save();
428 if (d->clipPainting)
429 painter->setClipRect(opt.rect);
430
431 // get the data and the rectangles
432
433 QVariant value;
434
435 QPixmap pixmap;
436 QRect decorationRect;
437 value = index.data(Qt::DecorationRole);
438 if (value.isValid()) {
439 // ### we need the pixmap to call the virtual function
440 pixmap = decoration(opt, value);
441 if (value.type() == QVariant::Icon) {
442 d->tmp.icon = qvariant_cast<QIcon>(value);
443 d->tmp.mode = d->iconMode(option.state);
444 d->tmp.state = d->iconState(option.state);
445 const QSize size = d->tmp.icon.actualSize(option.decorationSize,
446 d->tmp.mode, d->tmp.state);
447 decorationRect = QRect(QPoint(0, 0), size);
448 } else {
449 d->tmp.icon = QIcon();
450 decorationRect = QRect(QPoint(0, 0), pixmap.size());
451 }
452 } else {
453 d->tmp.icon = QIcon();
454 decorationRect = QRect();
455 }
456
457 QString text;
458 QRect displayRect;
459 value = index.data(Qt::DisplayRole);
460 if (value.isValid() && !value.isNull()) {
461 text = QItemDelegatePrivate::valueToText(value, opt);
462 displayRect = textRectangle(painter, d->textLayoutBounds(opt), opt.font, text);
463 }
464
465 QRect checkRect;
466 Qt::CheckState checkState = Qt::Unchecked;
467 value = index.data(Qt::CheckStateRole);
468 if (value.isValid()) {
469 checkState = static_cast<Qt::CheckState>(value.toInt());
470 checkRect = check(opt, opt.rect, value);
471 }
472
473 // do the layout
474
475 doLayout(opt, &checkRect, &decorationRect, &displayRect, false);
476
477 // draw the item
478
479 drawBackground(painter, opt, index);
480 drawCheck(painter, opt, checkRect, checkState);
481 drawDecoration(painter, opt, decorationRect, pixmap);
482 drawDisplay(painter, opt, displayRect, text);
483 drawFocus(painter, opt, displayRect);
484
485 // done
486 painter->restore();
487}
488
489/*!
490 Returns the size needed by the delegate to display the item
491 specified by \a index, taking into account the style information
492 provided by \a option.
493
494 When reimplementing this function, note that in case of text
495 items, QItemDelegate adds a margin (i.e. 2 *
496 QStyle::PM_FocusFrameHMargin) to the length of the text.
497*/
498
499QSize QItemDelegate::sizeHint(const QStyleOptionViewItem &option,
500 const QModelIndex &index) const
501{
502 QVariant value = index.data(Qt::SizeHintRole);
503 if (value.isValid())
504 return qvariant_cast<QSize>(value);
505 QRect decorationRect = rect(option, index, Qt::DecorationRole);
506 QRect displayRect = rect(option, index, Qt::DisplayRole);
507 QRect checkRect = rect(option, index, Qt::CheckStateRole);
508
509 doLayout(option, &checkRect, &decorationRect, &displayRect, true);
510
511 return (decorationRect|displayRect|checkRect).size();
512}
513
514/*!
515 Returns the widget used to edit the item specified by \a index
516 for editing. The \a parent widget and style \a option are used to
517 control how the editor widget appears.
518
519 \sa QAbstractItemDelegate::createEditor()
520*/
521
522QWidget *QItemDelegate::createEditor(QWidget *parent,
523 const QStyleOptionViewItem &,
524 const QModelIndex &index) const
525{
526 Q_D(const QItemDelegate);
527 if (!index.isValid())
528 return 0;
529 QVariant::Type t = static_cast<QVariant::Type>(index.data(Qt::EditRole).userType());
530 const QItemEditorFactory *factory = d->f;
531 if (factory == 0)
532 factory = QItemEditorFactory::defaultFactory();
533 return factory->createEditor(t, parent);
534}
535
536/*!
537 Sets the data to be displayed and edited by the \a editor from the
538 data model item specified by the model \a index.
539
540 The default implementation stores the data in the \a editor
541 widget's \l {Qt's Property System} {user property}.
542
543 \sa QMetaProperty::isUser()
544*/
545
546void QItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
547{
548#ifdef QT_NO_PROPERTIES
549 Q_UNUSED(editor);
550 Q_UNUSED(index);
551#else
552 Q_D(const QItemDelegate);
553 QVariant v = index.data(Qt::EditRole);
554 QByteArray n = editor->metaObject()->userProperty().name();
555
556 // ### Qt 5: remove
557 // A work-around for missing "USER true" in qdatetimeedit.h for
558 // QTimeEdit's time property and QDateEdit's date property.
559 // It only triggers if the default user property "dateTime" is
560 // reported for QTimeEdit and QDateEdit.
561 if (n == "dateTime") {
562 if (editor->inherits("QTimeEdit"))
563 n = "time";
564 else if (editor->inherits("QDateEdit"))
565 n = "date";
566 }
567
568 // ### Qt 5: give QComboBox a USER property
569 if (n.isEmpty() && editor->inherits("QComboBox"))
570 n = d->editorFactory()->valuePropertyName(static_cast<QVariant::Type>(v.userType()));
571 if (!n.isEmpty()) {
572 if (!v.isValid())
573 v = QVariant(editor->property(n).userType(), (const void *)0);
574 editor->setProperty(n, v);
575 }
576#endif
577}
578
579/*!
580 Gets data from the \a editor widget and stores it in the specified
581 \a model at the item \a index.
582
583 The default implementation gets the value to be stored in the data
584 model from the \a editor widget's \l {Qt's Property System} {user
585 property}.
586
587 \sa QMetaProperty::isUser()
588*/
589
590void QItemDelegate::setModelData(QWidget *editor,
591 QAbstractItemModel *model,
592 const QModelIndex &index) const
593{
594#ifdef QT_NO_PROPERTIES
595 Q_UNUSED(model);
596 Q_UNUSED(editor);
597 Q_UNUSED(index);
598#else
599 Q_D(const QItemDelegate);
600 Q_ASSERT(model);
601 Q_ASSERT(editor);
602 QByteArray n = editor->metaObject()->userProperty().name();
603 if (n.isEmpty())
604 n = d->editorFactory()->valuePropertyName(
605 static_cast<QVariant::Type>(model->data(index, Qt::EditRole).userType()));
606 if (!n.isEmpty())
607 model->setData(index, editor->property(n), Qt::EditRole);
608#endif
609}
610
611/*!
612 Updates the \a editor for the item specified by \a index
613 according to the style \a option given.
614*/
615
616void QItemDelegate::updateEditorGeometry(QWidget *editor,
617 const QStyleOptionViewItem &option,
618 const QModelIndex &index) const
619{
620 if (!editor)
621 return;
622 Q_ASSERT(index.isValid());
623 QPixmap pixmap = decoration(option, index.data(Qt::DecorationRole));
624 QString text = QItemDelegatePrivate::replaceNewLine(index.data(Qt::DisplayRole).toString());
625 QRect pixmapRect = QRect(QPoint(0, 0), option.decorationSize).intersected(pixmap.rect());
626 QRect textRect = textRectangle(0, option.rect, option.font, text);
627 QRect checkRect = check(option, textRect, index.data(Qt::CheckStateRole));
628 QStyleOptionViewItem opt = option;
629 opt.showDecorationSelected = true; // let the editor take up all available space
630 doLayout(opt, &checkRect, &pixmapRect, &textRect, false);
631 editor->setGeometry(textRect);
632}
633
634/*!
635 Returns the editor factory used by the item delegate.
636 If no editor factory is set, the function will return null.
637
638 \sa setItemEditorFactory()
639*/
640QItemEditorFactory *QItemDelegate::itemEditorFactory() const
641{
642 Q_D(const QItemDelegate);
643 return d->f;
644}
645
646/*!
647 Sets the editor factory to be used by the item delegate to be the \a factory
648 specified. If no editor factory is set, the item delegate will use the
649 default editor factory.
650
651 \sa itemEditorFactory()
652*/
653void QItemDelegate::setItemEditorFactory(QItemEditorFactory *factory)
654{
655 Q_D(QItemDelegate);
656 d->f = factory;
657}
658
659/*!
660 Renders the item view \a text within the rectangle specified by \a rect
661 using the given \a painter and style \a option.
662*/
663
664void QItemDelegate::drawDisplay(QPainter *painter, const QStyleOptionViewItem &option,
665 const QRect &rect, const QString &text) const
666{
667 Q_D(const QItemDelegate);
668
669 QPen pen = painter->pen();
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 (qVariantCanConvert<QBrush>(value)) {
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, '-', '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::fromUtf16(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 const QSize size = d->doTextLayout(rect.width()).toSize();
1152 // ###: textRectangle should take style option as argument
1153 const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
1154 return QRect(0, 0, size.width() + 2 * textMargin, size.height());
1155}
1156
1157/*!
1158 \fn bool QItemDelegate::eventFilter(QObject *editor, QEvent *event)
1159
1160 Returns true if the given \a editor is a valid QWidget and the
1161 given \a event is handled; otherwise returns false. The following
1162 key press events are handled by default:
1163
1164 \list
1165 \o \gui Tab
1166 \o \gui Backtab
1167 \o \gui Enter
1168 \o \gui Return
1169 \o \gui Esc
1170 \endlist
1171
1172 In the case of \gui Tab, \gui Backtab, \gui Enter and \gui Return
1173 key press events, the \a editor's data is comitted to the model
1174 and the editor is closed. If the \a event is a \gui Tab key press
1175 the view will open an editor on the next item in the
1176 view. Likewise, if the \a event is a \gui Backtab key press the
1177 view will open an editor on the \e previous item in the view.
1178
1179 If the event is a \gui Esc key press event, the \a editor is
1180 closed \e without committing its data.
1181
1182 \sa commitData(), closeEditor()
1183*/
1184
1185bool QItemDelegate::eventFilter(QObject *object, QEvent *event)
1186{
1187 QWidget *editor = qobject_cast<QWidget*>(object);
1188 if (!editor)
1189 return false;
1190 if (event->type() == QEvent::KeyPress) {
1191 switch (static_cast<QKeyEvent *>(event)->key()) {
1192 case Qt::Key_Tab:
1193 emit commitData(editor);
1194 emit closeEditor(editor, QAbstractItemDelegate::EditNextItem);
1195 return true;
1196 case Qt::Key_Backtab:
1197 emit commitData(editor);
1198 emit closeEditor(editor, QAbstractItemDelegate::EditPreviousItem);
1199 return true;
1200 case Qt::Key_Enter:
1201 case Qt::Key_Return:
1202#ifndef QT_NO_TEXTEDIT
1203 if (qobject_cast<QTextEdit *>(editor) || qobject_cast<QPlainTextEdit *>(editor))
1204 return false; // don't filter enter key events for QTextEdit
1205 // We want the editor to be able to process the key press
1206 // before committing the data (e.g. so it can do
1207 // validation/fixup of the input).
1208#endif // QT_NO_TEXTEDIT
1209#ifndef QT_NO_LINEEDIT
1210 if (QLineEdit *e = qobject_cast<QLineEdit*>(editor))
1211 if (!e->hasAcceptableInput())
1212 return false;
1213#endif // QT_NO_LINEEDIT
1214 QMetaObject::invokeMethod(this, "_q_commitDataAndCloseEditor",
1215 Qt::QueuedConnection, Q_ARG(QWidget*, editor));
1216 return false;
1217 case Qt::Key_Escape:
1218 // don't commit data
1219 emit closeEditor(editor, QAbstractItemDelegate::RevertModelCache);
1220 break;
1221 default:
1222 return false;
1223 }
1224 if (editor->parentWidget())
1225 editor->parentWidget()->setFocus();
1226 return true;
1227 } else if (event->type() == QEvent::FocusOut || (event->type() == QEvent::Hide && editor->isWindow())) {
1228 //the Hide event will take care of he editors that are in fact complete dialogs
1229 if (!editor->isActiveWindow() || (QApplication::focusWidget() != editor)) {
1230 QWidget *w = QApplication::focusWidget();
1231 while (w) { // don't worry about focus changes internally in the editor
1232 if (w == editor)
1233 return false;
1234 w = w->parentWidget();
1235 }
1236#ifndef QT_NO_DRAGANDDROP
1237 // The window may lose focus during an drag operation.
1238 // i.e when dragging involves the taskbar on Windows.
1239 if (QDragManager::self() && QDragManager::self()->object != 0)
1240 return false;
1241#endif
1242
1243 emit commitData(editor);
1244 emit closeEditor(editor, NoHint);
1245 }
1246 } else if (event->type() == QEvent::ShortcutOverride) {
1247 if (static_cast<QKeyEvent*>(event)->key() == Qt::Key_Escape) {
1248 event->accept();
1249 return true;
1250 }
1251 }
1252 return false;
1253}
1254
1255/*!
1256 \reimp
1257*/
1258
1259bool QItemDelegate::editorEvent(QEvent *event,
1260 QAbstractItemModel *model,
1261 const QStyleOptionViewItem &option,
1262 const QModelIndex &index)
1263{
1264 Q_ASSERT(event);
1265 Q_ASSERT(model);
1266
1267 // make sure that the item is checkable
1268 Qt::ItemFlags flags = model->flags(index);
1269 if (!(flags & Qt::ItemIsUserCheckable) || !(option.state & QStyle::State_Enabled)
1270 || !(flags & Qt::ItemIsEnabled))
1271 return false;
1272
1273 // make sure that we have a check state
1274 QVariant value = index.data(Qt::CheckStateRole);
1275 if (!value.isValid())
1276 return false;
1277
1278 // make sure that we have the right event type
1279 if ((event->type() == QEvent::MouseButtonRelease)
1280 || (event->type() == QEvent::MouseButtonDblClick)) {
1281 QRect checkRect = check(option, option.rect, Qt::Checked);
1282 QRect emptyRect;
1283 doLayout(option, &checkRect, &emptyRect, &emptyRect, false);
1284 QMouseEvent *me = static_cast<QMouseEvent*>(event);
1285 if (me->button() != Qt::LeftButton || !checkRect.contains(me->pos()))
1286 return false;
1287
1288 // eat the double click events inside the check rect
1289 if (event->type() == QEvent::MouseButtonDblClick)
1290 return true;
1291
1292 } else if (event->type() == QEvent::KeyPress) {
1293 if (static_cast<QKeyEvent*>(event)->key() != Qt::Key_Space
1294 && static_cast<QKeyEvent*>(event)->key() != Qt::Key_Select)
1295 return false;
1296 } else {
1297 return false;
1298 }
1299
1300 Qt::CheckState state;
1301 if ( flags & Qt::ItemIsTristate ) {
1302 state = static_cast<Qt::CheckState>( (value.toInt() + 1) % 3 );
1303 } else {
1304 state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
1305 ? Qt::Unchecked : Qt::Checked);
1306 }
1307
1308 return model->setData(index, state, Qt::CheckStateRole);
1309}
1310
1311/*!
1312 \internal
1313*/
1314
1315QStyleOptionViewItem QItemDelegate::setOptions(const QModelIndex &index,
1316 const QStyleOptionViewItem &option) const
1317{
1318 QStyleOptionViewItem opt = option;
1319
1320 // set font
1321 QVariant value = index.data(Qt::FontRole);
1322 if (value.isValid()){
1323 opt.font = qvariant_cast<QFont>(value).resolve(opt.font);
1324 opt.fontMetrics = QFontMetrics(opt.font);
1325 }
1326
1327 // set text alignment
1328 value = index.data(Qt::TextAlignmentRole);
1329 if (value.isValid())
1330 opt.displayAlignment = Qt::Alignment(value.toInt());
1331
1332 // set foreground brush
1333 value = index.data(Qt::ForegroundRole);
1334 if (qVariantCanConvert<QBrush>(value))
1335 opt.palette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value));
1336
1337 return opt;
1338}
1339
1340QT_END_NAMESPACE
1341
1342#include "moc_qitemdelegate.cpp"
1343
1344#endif // QT_NO_ITEMVIEWS
Note: See TracBrowser for help on using the repository browser.