source: trunk/src/gui/itemviews/qstyleditemdelegate.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 27.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 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 "qstyleditemdelegate.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 <private/qitemeditorfactory_p.h>
65#include <qmetaobject.h>
66#include <qtextlayout.h>
67#include <private/qobject_p.h>
68#include <private/qdnd_p.h>
69#include <private/qtextengine_p.h>
70#include <private/qlayoutengine_p.h>
71#include <qdebug.h>
72#include <qlocale.h>
73#include <qdialog.h>
74#include <qtableview.h>
75
76#include <limits.h>
77
78QT_BEGIN_NAMESPACE
79
80class QStyledItemDelegatePrivate : public QObjectPrivate
81{
82 Q_DECLARE_PUBLIC(QStyledItemDelegate)
83
84public:
85 QStyledItemDelegatePrivate() : factory(0) { }
86
87 static const QWidget *widget(const QStyleOptionViewItem &option)
88 {
89 if (const QStyleOptionViewItemV3 *v3 = qstyleoption_cast<const QStyleOptionViewItemV3 *>(&option))
90 return v3->widget;
91 return 0;
92 }
93
94 const QItemEditorFactory *editorFactory() const
95 {
96 return factory ? factory : QItemEditorFactory::defaultFactory();
97 }
98
99 void _q_commitDataAndCloseEditor(QWidget *editor)
100 {
101 Q_Q(QStyledItemDelegate);
102 emit q->commitData(editor);
103 emit q->closeEditor(editor, QAbstractItemDelegate::SubmitModelCache);
104 }
105 QItemEditorFactory *factory;
106};
107
108/*!
109 \class QStyledItemDelegate
110
111 \brief The QStyledItemDelegate class provides display and editing facilities for
112 data items from a model.
113
114 \ingroup model-view
115
116 \since 4.4
117
118 When displaying data from models in Qt item views, e.g., a
119 QTableView, the individual items are drawn by a delegate. Also,
120 when an item is edited, it provides an editor widget, which is
121 placed on top of the item view while editing takes place.
122 QStyledItemDelegate is the default delegate for all Qt item
123 views, and is installed upon them when they are created.
124
125 The QStyledItemDelegate class is one of the \l{Model/View Classes}
126 and is part of Qt's \l{Model/View Programming}{model/view
127 framework}. The delegate allows the display and editing of items
128 to be developed independently from the model and view.
129
130 The data of items in models are assigned an
131 \l{Qt::}{ItemDataRole}; each item can store a QVariant for each
132 role. QStyledItemDelegate implements display and editing for the
133 most common datatypes expected by users, including booleans,
134 integers, and strings.
135
136 The data will be drawn differently depending on which role they
137 have in the model. The following table describes the roles and the
138 data types the delegate can handle for each of them. It is often
139 sufficient to ensure that the model returns appropriate data for
140 each of the roles to determine the appearance of items in views.
141
142 \table
143 \header \o Role \o Accepted Types
144 \omit
145 \row \o \l Qt::AccessibleDescriptionRole \o QString
146 \row \o \l Qt::AccessibleTextRole \o QString
147 \endomit
148 \row \o \l Qt::BackgroundRole \o QBrush
149 \row \o \l Qt::BackgroundColorRole \o QColor (obsolete; use Qt::BackgroundRole instead)
150 \row \o \l Qt::CheckStateRole \o Qt::CheckState
151 \row \o \l Qt::DecorationRole \o QIcon, QPixmap, QImage and QColor
152 \row \o \l Qt::DisplayRole \o QString and types with a string representation
153 \row \o \l Qt::EditRole \o See QItemEditorFactory for details
154 \row \o \l Qt::FontRole \o QFont
155 \row \o \l Qt::SizeHintRole \o QSize
156 \omit
157 \row \o \l Qt::StatusTipRole \o
158 \endomit
159 \row \o \l Qt::TextAlignmentRole \o Qt::Alignment
160 \row \o \l Qt::ForegroundRole \o QBrush
161 \row \o \l Qt::TextColorRole \o QColor (obsolete; use Qt::ForegroundRole instead)
162 \omit
163 \row \o \l Qt::ToolTipRole
164 \row \o \l Qt::WhatsThisRole
165 \endomit
166 \endtable
167
168 Editors are created with a QItemEditorFactory; a default static
169 instance provided by QItemEditorFactory is installed on all item
170 delegates. You can set a custom factory using
171 setItemEditorFactory() or set a new default factory with
172 QItemEditorFactory::setDefaultFactory(). It is the data stored in
173 the item model with the \l{Qt::}{EditRole} that is edited. See the
174 QItemEditorFactory class for a more high-level introduction to
175 item editor factories. The \l{Color Editor Factory Example}{Color
176 Editor Factory} example shows how to create custom editors with a
177 factory.
178
179 \section1 Subclassing QStyledItemDelegate
180
181 If the delegate does not support painting of the data types you
182 need or you want to customize the drawing of items, you need to
183 subclass QStyledItemDelegate, and reimplement paint() and possibly
184 sizeHint(). The paint() function is called individually for each
185 item, and with sizeHint(), you can specify the hint for each
186 of them.
187
188 When reimplementing paint(), one would typically handle the
189 datatypes one would like to draw and use the superclass
190 implementation for other types.
191
192 The painting of check box indicators are performed by the current
193 style. The style also specifies the size and the bounding
194 rectangles in which to draw the data for the different data roles.
195 The bounding rectangle of the item itself is also calculated by
196 the style. When drawing already supported datatypes, it is
197 therefore a good idea to ask the style for these bounding
198 rectangles. The QStyle class description describes this in
199 more detail.
200
201 If you wish to change any of the bounding rectangles calculated by
202 the style or the painting of check box indicators, you can
203 subclass QStyle. Note, however, that the size of the items can
204 also be affected by reimplementing sizeHint().
205
206 It is possible for a custom delegate to provide editors
207 without the use of an editor item factory. In this case, the
208 following virtual functions must be reimplemented:
209
210 \list
211 \o createEditor() returns the widget used to change data from the model
212 and can be reimplemented to customize editing behavior.
213 \o setEditorData() provides the widget with data to manipulate.
214 \o updateEditorGeometry() ensures that the editor is displayed correctly
215 with respect to the item view.
216 \o setModelData() returns updated data to the model.
217 \endlist
218
219 The \l{Star Delegate Example}{Star Delegate} example creates
220 editors by reimplementing these methods.
221
222 \section1 QStyledItemDelegate vs. QItemDelegate
223
224 Since Qt 4.4, there are two delegate classes: QItemDelegate and
225 QStyledItemDelegate. However, the default delegate is QStyledItemDelegate.
226 These two classes are independent alternatives to painting and providing
227 editors for items in views. The difference between them is that
228 QStyledItemDelegate uses the current style to paint its items. We therefore
229 recommend using QStyledItemDelegate as the base class when implementing
230 custom delegates or when working with Qt style sheets. The code required
231 for either class should be equal unless the custom delegate needs to use
232 the style for drawing.
233
234 If you wish to customize the painting of item views, you should
235 implement a custom style. Please see the QStyle class
236 documentation for details.
237
238 \sa {Delegate Classes}, QItemDelegate, QAbstractItemDelegate, QStyle,
239 {Spin Box Delegate Example}, {Star Delegate Example}, {Color
240 Editor Factory Example}
241*/
242
243
244/*!
245 Constructs an item delegate with the given \a parent.
246*/
247QStyledItemDelegate::QStyledItemDelegate(QObject *parent)
248 : QAbstractItemDelegate(*new QStyledItemDelegatePrivate(), parent)
249{
250}
251
252/*!
253 Destroys the item delegate.
254*/
255QStyledItemDelegate::~QStyledItemDelegate()
256{
257}
258
259/*!
260 This function returns the string that the delegate will use to display the
261 Qt::DisplayRole of the model in \a locale. \a value is the value of the Qt::DisplayRole
262 provided by the model.
263
264 The default implementation uses the QLocale::toString to convert \a value into
265 a QString.
266*/
267QString QStyledItemDelegate::displayText(const QVariant &value, const QLocale& locale) const
268{
269 QString text;
270 switch (value.userType()) {
271 case QMetaType::Float:
272 case QVariant::Double:
273 text = locale.toString(value.toReal());
274 break;
275 case QVariant::Int:
276 case QVariant::LongLong:
277 text = locale.toString(value.toLongLong());
278 break;
279 case QVariant::UInt:
280 case QVariant::ULongLong:
281 text = locale.toString(value.toULongLong());
282 break;
283 case QVariant::Date:
284 text = locale.toString(value.toDate(), QLocale::ShortFormat);
285 break;
286 case QVariant::Time:
287 text = locale.toString(value.toTime(), QLocale::ShortFormat);
288 break;
289 case QVariant::DateTime:
290 text = locale.toString(value.toDateTime().date(), QLocale::ShortFormat);
291 text += QLatin1Char(' ');
292 text += locale.toString(value.toDateTime().time(), QLocale::ShortFormat);
293 break;
294 default:
295 // convert new lines into line separators
296 text = value.toString();
297 for (int i = 0; i < text.count(); ++i) {
298 if (text.at(i) == QLatin1Char('\n'))
299 text[i] = QChar::LineSeparator;
300 }
301 break;
302 }
303 return text;
304}
305
306/*!
307 Initialize \a option with the values using the index \a index. This method
308 is useful for subclasses when they need a QStyleOptionViewItem, but don't want
309 to fill in all the information themselves. This function will check the version
310 of the QStyleOptionViewItem and fill in the additional values for a
311 QStyleOptionViewItemV2, QStyleOptionViewItemV3 and QStyleOptionViewItemV4.
312
313 \sa QStyleOption::initFrom()
314*/
315void QStyledItemDelegate::initStyleOption(QStyleOptionViewItem *option,
316 const QModelIndex &index) const
317{
318 QVariant value = index.data(Qt::FontRole);
319 if (value.isValid() && !value.isNull()) {
320 option->font = qvariant_cast<QFont>(value).resolve(option->font);
321 option->fontMetrics = QFontMetrics(option->font);
322 }
323
324 value = index.data(Qt::TextAlignmentRole);
325 if (value.isValid() && !value.isNull())
326 option->displayAlignment = Qt::Alignment(value.toInt());
327
328 value = index.data(Qt::ForegroundRole);
329 if (qVariantCanConvert<QBrush>(value))
330 option->palette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value));
331
332 if (QStyleOptionViewItemV4 *v4 = qstyleoption_cast<QStyleOptionViewItemV4 *>(option)) {
333 v4->index = index;
334 QVariant value = index.data(Qt::CheckStateRole);
335 if (value.isValid() && !value.isNull()) {
336 v4->features |= QStyleOptionViewItemV2::HasCheckIndicator;
337 v4->checkState = static_cast<Qt::CheckState>(value.toInt());
338 }
339
340 value = index.data(Qt::DecorationRole);
341 if (value.isValid() && !value.isNull()) {
342 v4->features |= QStyleOptionViewItemV2::HasDecoration;
343 switch (value.type()) {
344 case QVariant::Icon: {
345 v4->icon = qvariant_cast<QIcon>(value);
346 QIcon::Mode mode;
347 if (!(option->state & QStyle::State_Enabled))
348 mode = QIcon::Disabled;
349 else if (option->state & QStyle::State_Selected)
350 mode = QIcon::Selected;
351 else
352 mode = QIcon::Normal;
353 QIcon::State state = option->state & QStyle::State_Open ? QIcon::On : QIcon::Off;
354 v4->decorationSize = v4->icon.actualSize(option->decorationSize, mode, state);
355 break;
356 }
357 case QVariant::Color: {
358 QPixmap pixmap(option->decorationSize);
359 pixmap.fill(qvariant_cast<QColor>(value));
360 v4->icon = QIcon(pixmap);
361 break;
362 }
363 case QVariant::Image: {
364 QImage image = qvariant_cast<QImage>(value);
365 v4->icon = QIcon(QPixmap::fromImage(image));
366 v4->decorationSize = image.size();
367 break;
368 }
369 case QVariant::Pixmap: {
370 QPixmap pixmap = qvariant_cast<QPixmap>(value);
371 v4->icon = QIcon(pixmap);
372 v4->decorationSize = pixmap.size();
373 break;
374 }
375 default:
376 break;
377 }
378 }
379
380 value = index.data(Qt::DisplayRole);
381 if (value.isValid() && !value.isNull()) {
382 v4->features |= QStyleOptionViewItemV2::HasDisplay;
383 v4->text = displayText(value, v4->locale);
384 }
385
386 v4->backgroundBrush = qvariant_cast<QBrush>(index.data(Qt::BackgroundRole));
387 }
388}
389
390/*!
391 Renders the delegate using the given \a painter and style \a option for
392 the item specified by \a index.
393
394 This function paints the item using the view's QStyle.
395
396 When reimplementing paint in a subclass. Use the initStyleOption()
397 to set up the \a option in the same way as the
398 QStyledItemDelegate; the option will always be an instance of
399 QStyleOptionViewItemV4. Please see its class description for
400 information on its contents.
401
402 Whenever possible, use the \a option while painting.
403 Especially its \l{QStyleOption::}{rect} variable to decide
404 where to draw and its \l{QStyleOption::}{state} to determine
405 if it is enabled or selected.
406
407 After painting, you should ensure that the painter is returned to
408 its the state it was supplied in when this function was called.
409 For example, it may be useful to call QPainter::save() before
410 painting and QPainter::restore() afterwards.
411
412 \sa QItemDelegate::paint(), QStyle::drawControl(), QStyle::CE_ItemViewItem
413*/
414void QStyledItemDelegate::paint(QPainter *painter,
415 const QStyleOptionViewItem &option, const QModelIndex &index) const
416{
417 Q_ASSERT(index.isValid());
418
419 QStyleOptionViewItemV4 opt = option;
420 initStyleOption(&opt, index);
421
422 const QWidget *widget = QStyledItemDelegatePrivate::widget(option);
423 QStyle *style = widget ? widget->style() : QApplication::style();
424 style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
425}
426
427/*!
428 Returns the size needed by the delegate to display the item
429 specified by \a index, taking into account the style information
430 provided by \a option.
431
432 This function uses the view's QStyle to determine the size of the
433 item.
434
435 \sa QStyle::sizeFromContents(), QStyle::CT_ItemViewItem
436*/
437QSize QStyledItemDelegate::sizeHint(const QStyleOptionViewItem &option,
438 const QModelIndex &index) const
439{
440 QVariant value = index.data(Qt::SizeHintRole);
441 if (value.isValid())
442 return qvariant_cast<QSize>(value);
443
444 QStyleOptionViewItemV4 opt = option;
445 initStyleOption(&opt, index);
446 const QWidget *widget = QStyledItemDelegatePrivate::widget(option);
447 QStyle *style = widget ? widget->style() : QApplication::style();
448 return style->sizeFromContents(QStyle::CT_ItemViewItem, &opt, QSize(), widget);
449}
450
451/*!
452 Returns the widget used to edit the item specified by \a index
453 for editing. The \a parent widget and style \a option are used to
454 control how the editor widget appears.
455
456 \sa QAbstractItemDelegate::createEditor()
457*/
458QWidget *QStyledItemDelegate::createEditor(QWidget *parent,
459 const QStyleOptionViewItem &,
460 const QModelIndex &index) const
461{
462 Q_D(const QStyledItemDelegate);
463 if (!index.isValid())
464 return 0;
465 QVariant::Type t = static_cast<QVariant::Type>(index.data(Qt::EditRole).userType());
466 return d->editorFactory()->createEditor(t, parent);
467}
468
469/*!
470 Sets the data to be displayed and edited by the \a editor from the
471 data model item specified by the model \a index.
472
473 The default implementation stores the data in the \a editor
474 widget's \l {Qt's Property System} {user property}.
475
476 \sa QMetaProperty::isUser()
477*/
478void QStyledItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
479{
480#ifdef QT_NO_PROPERTIES
481 Q_UNUSED(editor);
482 Q_UNUSED(index);
483#else
484 Q_D(const QStyledItemDelegate);
485 QVariant v = index.data(Qt::EditRole);
486 QByteArray n = editor->metaObject()->userProperty().name();
487
488 // ### Qt 5: remove
489 // A work-around for missing "USER true" in qdatetimeedit.h for
490 // QTimeEdit's time property and QDateEdit's date property.
491 // It only triggers if the default user property "dateTime" is
492 // reported for QTimeEdit and QDateEdit.
493 if (n == "dateTime") {
494 if (editor->inherits("QTimeEdit"))
495 n = "time";
496 else if (editor->inherits("QDateEdit"))
497 n = "date";
498 }
499
500 // ### Qt 5: give QComboBox a USER property
501 if (n.isEmpty() && editor->inherits("QComboBox"))
502 n = d->editorFactory()->valuePropertyName(static_cast<QVariant::Type>(v.userType()));
503 if (!n.isEmpty()) {
504 if (!v.isValid())
505 v = QVariant(editor->property(n).userType(), (const void *)0);
506 editor->setProperty(n, v);
507 }
508#endif
509}
510
511/*!
512 Gets data from the \a editor widget and stores it in the specified
513 \a model at the item \a index.
514
515 The default implementation gets the value to be stored in the data
516 model from the \a editor widget's \l {Qt's Property System} {user
517 property}.
518
519 \sa QMetaProperty::isUser()
520*/
521void QStyledItemDelegate::setModelData(QWidget *editor,
522 QAbstractItemModel *model,
523 const QModelIndex &index) const
524{
525#ifdef QT_NO_PROPERTIES
526 Q_UNUSED(model);
527 Q_UNUSED(editor);
528 Q_UNUSED(index);
529#else
530 Q_D(const QStyledItemDelegate);
531 Q_ASSERT(model);
532 Q_ASSERT(editor);
533 QByteArray n = editor->metaObject()->userProperty().name();
534 if (n.isEmpty())
535 n = d->editorFactory()->valuePropertyName(
536 static_cast<QVariant::Type>(model->data(index, Qt::EditRole).userType()));
537 if (!n.isEmpty())
538 model->setData(index, editor->property(n), Qt::EditRole);
539#endif
540}
541
542/*!
543 Updates the \a editor for the item specified by \a index
544 according to the style \a option given.
545*/
546void QStyledItemDelegate::updateEditorGeometry(QWidget *editor,
547 const QStyleOptionViewItem &option,
548 const QModelIndex &index) const
549{
550 if (!editor)
551 return;
552 Q_ASSERT(index.isValid());
553 const QWidget *widget = QStyledItemDelegatePrivate::widget(option);
554
555 QStyleOptionViewItemV4 opt = option;
556 initStyleOption(&opt, index);
557 // let the editor take up all available space
558 //if the editor is not a QLineEdit
559 //or it is in a QTableView
560#if !defined(QT_NO_TABLEVIEW) && !defined(QT_NO_LINEEDIT)
561 if (qobject_cast<QExpandingLineEdit*>(editor) && !qobject_cast<const QTableView*>(widget))
562 opt.showDecorationSelected = editor->style()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, 0, editor);
563 else
564#endif
565 opt.showDecorationSelected = true;
566
567 QStyle *style = widget ? widget->style() : QApplication::style();
568 QRect geom = style->subElementRect(QStyle::SE_ItemViewItemText, &opt, widget);
569 if ( editor->layoutDirection() == Qt::RightToLeft) {
570 const int delta = qSmartMinSize(editor).width() - geom.width();
571 if (delta > 0) {
572 //we need to widen the geometry
573 geom.adjust(-delta, 0, 0, 0);
574 }
575 }
576
577 editor->setGeometry(geom);
578}
579
580/*!
581 Returns the editor factory used by the item delegate.
582 If no editor factory is set, the function will return null.
583
584 \sa setItemEditorFactory()
585*/
586QItemEditorFactory *QStyledItemDelegate::itemEditorFactory() const
587{
588 Q_D(const QStyledItemDelegate);
589 return d->factory;
590}
591
592/*!
593 Sets the editor factory to be used by the item delegate to be the \a factory
594 specified. If no editor factory is set, the item delegate will use the
595 default editor factory.
596
597 \sa itemEditorFactory()
598*/
599void QStyledItemDelegate::setItemEditorFactory(QItemEditorFactory *factory)
600{
601 Q_D(QStyledItemDelegate);
602 d->factory = factory;
603}
604
605
606/*!
607 \fn bool QStyledItemDelegate::eventFilter(QObject *editor, QEvent *event)
608
609 Returns true if the given \a editor is a valid QWidget and the
610 given \a event is handled; otherwise returns false. The following
611 key press events are handled by default:
612
613 \list
614 \o \gui Tab
615 \o \gui Backtab
616 \o \gui Enter
617 \o \gui Return
618 \o \gui Esc
619 \endlist
620
621 In the case of \gui Tab, \gui Backtab, \gui Enter and \gui Return
622 key press events, the \a editor's data is comitted to the model
623 and the editor is closed. If the \a event is a \gui Tab key press
624 the view will open an editor on the next item in the
625 view. Likewise, if the \a event is a \gui Backtab key press the
626 view will open an editor on the \e previous item in the view.
627
628 If the event is a \gui Esc key press event, the \a editor is
629 closed \e without committing its data.
630
631 \sa commitData(), closeEditor()
632*/
633bool QStyledItemDelegate::eventFilter(QObject *object, QEvent *event)
634{
635 QWidget *editor = qobject_cast<QWidget*>(object);
636 if (!editor)
637 return false;
638 if (event->type() == QEvent::KeyPress) {
639 switch (static_cast<QKeyEvent *>(event)->key()) {
640 case Qt::Key_Tab:
641 emit commitData(editor);
642 emit closeEditor(editor, QAbstractItemDelegate::EditNextItem);
643 return true;
644 case Qt::Key_Backtab:
645 emit commitData(editor);
646 emit closeEditor(editor, QAbstractItemDelegate::EditPreviousItem);
647 return true;
648 case Qt::Key_Enter:
649 case Qt::Key_Return:
650#ifndef QT_NO_TEXTEDIT
651 if (qobject_cast<QTextEdit *>(editor) || qobject_cast<QPlainTextEdit *>(editor))
652 return false; // don't filter enter key events for QTextEdit
653 // We want the editor to be able to process the key press
654 // before committing the data (e.g. so it can do
655 // validation/fixup of the input).
656#endif // QT_NO_TEXTEDIT
657#ifndef QT_NO_LINEEDIT
658 if (QLineEdit *e = qobject_cast<QLineEdit*>(editor))
659 if (!e->hasAcceptableInput())
660 return false;
661#endif // QT_NO_LINEEDIT
662 QMetaObject::invokeMethod(this, "_q_commitDataAndCloseEditor",
663 Qt::QueuedConnection, Q_ARG(QWidget*, editor));
664 return false;
665 case Qt::Key_Escape:
666 // don't commit data
667 emit closeEditor(editor, QAbstractItemDelegate::RevertModelCache);
668 break;
669 default:
670 return false;
671 }
672 if (editor->parentWidget())
673 editor->parentWidget()->setFocus();
674 return true;
675 } else if (event->type() == QEvent::FocusOut || (event->type() == QEvent::Hide && editor->isWindow())) {
676 //the Hide event will take care of he editors that are in fact complete dialogs
677 if (!editor->isActiveWindow() || (QApplication::focusWidget() != editor)) {
678 QWidget *w = QApplication::focusWidget();
679 while (w) { // don't worry about focus changes internally in the editor
680 if (w == editor)
681 return false;
682 w = w->parentWidget();
683 }
684#ifndef QT_NO_DRAGANDDROP
685 // The window may lose focus during an drag operation.
686 // i.e when dragging involves the taskbar on Windows.
687 if (QDragManager::self() && QDragManager::self()->object != 0)
688 return false;
689#endif
690
691 emit commitData(editor);
692 emit closeEditor(editor, NoHint);
693 }
694 } else if (event->type() == QEvent::ShortcutOverride) {
695 if (static_cast<QKeyEvent*>(event)->key() == Qt::Key_Escape) {
696 event->accept();
697 return true;
698 }
699 }
700 return false;
701}
702
703/*!
704 \reimp
705*/
706bool QStyledItemDelegate::editorEvent(QEvent *event,
707 QAbstractItemModel *model,
708 const QStyleOptionViewItem &option,
709 const QModelIndex &index)
710{
711 Q_ASSERT(event);
712 Q_ASSERT(model);
713
714 // make sure that the item is checkable
715 Qt::ItemFlags flags = model->flags(index);
716 if (!(flags & Qt::ItemIsUserCheckable) || !(option.state & QStyle::State_Enabled)
717 || !(flags & Qt::ItemIsEnabled))
718 return false;
719
720 // make sure that we have a check state
721 QVariant value = index.data(Qt::CheckStateRole);
722 if (!value.isValid())
723 return false;
724
725 const QWidget *widget = QStyledItemDelegatePrivate::widget(option);
726 QStyle *style = widget ? widget->style() : QApplication::style();
727
728 // make sure that we have the right event type
729 if ((event->type() == QEvent::MouseButtonRelease)
730 || (event->type() == QEvent::MouseButtonDblClick)) {
731 QStyleOptionViewItemV4 viewOpt(option);
732 initStyleOption(&viewOpt, index);
733 QRect checkRect = style->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &viewOpt, widget);
734 QMouseEvent *me = static_cast<QMouseEvent*>(event);
735 if (me->button() != Qt::LeftButton || !checkRect.contains(me->pos()))
736 return false;
737
738 // eat the double click events inside the check rect
739 if (event->type() == QEvent::MouseButtonDblClick)
740 return true;
741
742 } else if (event->type() == QEvent::KeyPress) {
743 if (static_cast<QKeyEvent*>(event)->key() != Qt::Key_Space
744 && static_cast<QKeyEvent*>(event)->key() != Qt::Key_Select)
745 return false;
746 } else {
747 return false;
748 }
749
750 Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
751 ? Qt::Unchecked : Qt::Checked);
752 return model->setData(index, state, Qt::CheckStateRole);
753}
754
755QT_END_NAMESPACE
756
757#include "moc_qstyleditemdelegate.cpp"
758
759#endif // QT_NO_ITEMVIEWS
Note: See TracBrowser for help on using the repository browser.