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

Last change on this file since 349 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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