src/gui/itemviews/qstyleditemdelegate.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gui/itemviews/qstyleditemdelegate.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,764 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstyleditemdelegate.h"
+
+#ifndef QT_NO_ITEMVIEWS
+#include <qabstractitemmodel.h>
+#include <qapplication.h>
+#include <qbrush.h>
+#include <qlineedit.h>
+#include <qtextedit.h>
+#include <qplaintextedit.h>
+#include <qpainter.h>
+#include <qpalette.h>
+#include <qpoint.h>
+#include <qrect.h>
+#include <qsize.h>
+#include <qstyle.h>
+#include <qdatetime.h>
+#include <qstyleoption.h>
+#include <qevent.h>
+#include <qpixmap.h>
+#include <qbitmap.h>
+#include <qpixmapcache.h>
+#include <qitemeditorfactory.h>
+#include <private/qitemeditorfactory_p.h>
+#include <qmetaobject.h>
+#include <qtextlayout.h>
+#include <private/qobject_p.h>
+#include <private/qdnd_p.h>
+#include <private/qtextengine_p.h>
+#include <private/qlayoutengine_p.h>
+#include <qdebug.h>
+#include <qlocale.h>
+#include <qdialog.h>
+#include <qtableview.h>
+
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+class QStyledItemDelegatePrivate : public QObjectPrivate
+{
+    Q_DECLARE_PUBLIC(QStyledItemDelegate)
+
+public:
+    QStyledItemDelegatePrivate() : factory(0) { }
+
+    static const QWidget *widget(const QStyleOptionViewItem &option)
+    {
+        if (const QStyleOptionViewItemV3 *v3 = qstyleoption_cast<const QStyleOptionViewItemV3 *>(&option))
+            return v3->widget;
+        return 0;
+    }
+
+    const QItemEditorFactory *editorFactory() const
+    {
+        return factory ? factory : QItemEditorFactory::defaultFactory();
+    }
+
+    void _q_commitDataAndCloseEditor(QWidget *editor)
+    {
+        Q_Q(QStyledItemDelegate);
+        emit q->commitData(editor);
+        emit q->closeEditor(editor, QAbstractItemDelegate::SubmitModelCache);
+    }
+    QItemEditorFactory *factory;
+};
+
+/*!
+    \class QStyledItemDelegate
+
+    \brief The QStyledItemDelegate class provides display and editing facilities for
+    data items from a model.
+
+    \ingroup model-view
+
+    \since 4.4
+
+    When displaying data from models in Qt item views, e.g., a
+    QTableView, the individual items are drawn by a delegate. Also,
+    when an item is edited, it provides an editor widget, which is
+    placed on top of the item view while editing takes place.
+    QStyledItemDelegate is the default delegate for all Qt item
+    views, and is installed upon them when they are created.
+
+    The QStyledItemDelegate class is one of the \l{Model/View Classes}
+    and is part of Qt's \l{Model/View Programming}{model/view
+    framework}. The delegate allows the display and editing of items
+    to be developed independently from the model and view.
+
+    The data of items in models are assigned an
+    \l{Qt::}{ItemDataRole}; each item can store a QVariant for each
+    role. QStyledItemDelegate implements display and editing for the
+    most common datatypes expected by users, including booleans,
+    integers, and strings.
+
+    The data will be drawn differently depending on which role they
+    have in the model. The following table describes the roles and the
+    data types the delegate can handle for each of them. It is often
+    sufficient to ensure that the model returns appropriate data for
+    each of the roles to determine the appearance of items in views.
+
+    \table
+    \header \o Role \o Accepted Types
+    \omit
+    \row    \o \l Qt::AccessibleDescriptionRole \o QString
+    \row    \o \l Qt::AccessibleTextRole \o QString
+    \endomit
+    \row    \o \l Qt::BackgroundRole \o QBrush
+    \row    \o \l Qt::BackgroundColorRole \o QColor (obsolete; use Qt::BackgroundRole instead)
+    \row    \o \l Qt::CheckStateRole \o Qt::CheckState
+    \row    \o \l Qt::DecorationRole \o QIcon and QColor
+    \row    \o \l Qt::DisplayRole \o QString and types with a string representation
+    \row    \o \l Qt::EditRole \o See QItemEditorFactory for details
+    \row    \o \l Qt::FontRole \o QFont
+    \row    \o \l Qt::SizeHintRole \o QSize
+    \omit
+    \row    \o \l Qt::StatusTipRole \o
+    \endomit
+    \row    \o \l Qt::TextAlignmentRole \o Qt::Alignment
+    \row    \o \l Qt::ForegroundRole \o QBrush
+    \row    \o \l Qt::TextColorRole \o QColor (obsolete; use Qt::ForegroundRole instead)
+    \omit
+    \row    \o \l Qt::ToolTipRole
+    \row    \o \l Qt::WhatsThisRole
+    \endomit
+    \endtable
+
+    Editors are created with a QItemEditorFactory; a default static
+    instance provided by QItemEditorFactory is installed on all item
+    delegates. You can set a custom factory using
+    setItemEditorFactory() or set a new default factory with
+    QItemEditorFactory::setDefaultFactory(). It is the data stored in
+    the item model with the \l{Qt::}{EditRole} that is edited. See the
+    QItemEditorFactory class for a more high-level introduction to
+    item editor factories. The \l{Color Editor Factory Example}{Color
+    Editor Factory} example shows how to create custom editors with a
+    factory.
+
+    \section1 Subclassing QStyledItemDelegate
+
+    If the delegate does not support painting of the data types you
+    need or you want to customize the drawing of items, you need to
+    subclass QStyledItemDelegate, and reimplement paint() and possibly
+    sizeHint(). The paint() function is called individually for each
+    item, and with sizeHint(), you can specify the hint for each
+    of them.
+
+    When reimplementing paint(), one would typically handle the
+    datatypes one would like to draw and use the superclass
+    implementation for other types.
+
+    The painting of check box indicators are performed by the current
+    style. The style also specifies the size and the bounding
+    rectangles in which to draw the data for the different data roles.
+    The bounding rectangle of the item itself is also calculated by
+    the style. When drawing already supported datatypes, it is
+    therefore a good idea to ask the style for these bounding
+    rectangles. The QStyle class description describes this in
+    more detail.
+
+    If you wish to change any of the bounding rectangles calculated by
+    the style or the painting of check box indicators, you can
+    subclass QStyle. Note, however, that the size of the items can
+    also be affected by reimplementing sizeHint().
+
+    It is possible for a custom delegate to provide editors
+    without the use of an editor item factory. In this case, the
+    following virtual functions must be reimplemented:
+
+    \list
+        \o createEditor() returns the widget used to change data from the model
+           and can be reimplemented to customize editing behavior.
+        \o setEditorData() provides the widget with data to manipulate.
+        \o updateEditorGeometry() ensures that the editor is displayed correctly
+           with respect to the item view.
+        \o setModelData() returns updated data to the model.
+    \endlist
+
+    The \l{Star Delegate Example}{Star Delegate} example creates
+    editors by reimplementing these methods.
+
+    \section1 QStyledItemDelegate vs. QItemDelegate
+
+    Since Qt 4.4, there are two delegate classes: QItemDelegate and
+    QStyledItemDelegate. However, the default delegate is QStyledItemDelegate.
+    These two classes are independent alternatives to painting and providing
+    editors for items in views. The difference between them is that
+    QStyledItemDelegate uses the current style to paint its items. We therefore
+    recommend using QStyledItemDelegate as the base class when implementing
+    custom delegates or when working with Qt style sheets. The code required
+    for either class should be equal unless the custom delegate needs to use
+    the style for drawing.
+
+    If you wish to customize the painting of item views, you should
+    implement a custom style. Please see the QStyle class
+    documentation for details.
+
+    \sa {Delegate Classes}, QItemDelegate, QAbstractItemDelegate, QStyle,
+        {Spin Box Delegate Example}, {Star Delegate Example}, {Color
+         Editor Factory Example}
+*/
+
+
+/*!
+    Constructs an item delegate with the given \a parent.
+*/
+QStyledItemDelegate::QStyledItemDelegate(QObject *parent)
+    : QAbstractItemDelegate(*new QStyledItemDelegatePrivate(), parent)
+{
+}
+
+/*!
+    Destroys the item delegate.
+*/
+QStyledItemDelegate::~QStyledItemDelegate()
+{
+}
+
+/*!
+    This function returns the string that the delegate will use to display the
+    Qt::DisplayRole of the model in \a locale. \a value is the value of the Qt::DisplayRole
+    provided by the model.
+
+    The default implementation uses the QLocale::toString to convert \a value into
+    a QString.
+*/
+QString QStyledItemDelegate::displayText(const QVariant &value, const QLocale& locale) const
+{
+    QString text;
+    switch (value.userType()) {
+    case QMetaType::Float:
+    case QVariant::Double:
+        text = locale.toString(value.toReal());
+        break;
+    case QVariant::Int:
+    case QVariant::LongLong:
+        text = locale.toString(value.toLongLong());
+        break;
+    case QVariant::UInt:
+    case QVariant::ULongLong:
+        text = locale.toString(value.toULongLong());
+        break;
+    case QVariant::Date:
+        text = locale.toString(value.toDate(), QLocale::ShortFormat);
+        break;
+    case QVariant::Time:
+        text = locale.toString(value.toTime(), QLocale::ShortFormat);
+        break;
+    case QVariant::DateTime:
+        text = locale.toString(value.toDateTime().date(), QLocale::ShortFormat);
+        text += QLatin1Char(' ');
+        text += locale.toString(value.toDateTime().time(), QLocale::ShortFormat);
+        break;
+    default:
+        // convert new lines into line separators
+        text = value.toString();
+        for (int i = 0; i < text.count(); ++i) {
+            if (text.at(i) == QLatin1Char('\n'))
+                text[i] = QChar::LineSeparator;
+        }
+        break;
+    }
+    return text;
+}
+
+/*!
+    Initialize \a option with the values using the index \a index. This method
+    is useful for subclasses when they need a QStyleOptionViewItem, but don't want
+    to fill in all the information themselves. This function will check the version
+    of the QStyleOptionViewItem and fill in the additional values for a
+    QStyleOptionViewItemV2, QStyleOptionViewItemV3 and QStyleOptionViewItemV4.
+
+    \sa QStyleOption::initFrom()
+*/
+void QStyledItemDelegate::initStyleOption(QStyleOptionViewItem *option,
+                                         const QModelIndex &index) const
+{
+    QVariant value = index.data(Qt::FontRole);
+    if (value.isValid() && !value.isNull()) {
+        option->font = qvariant_cast<QFont>(value).resolve(option->font);
+        option->fontMetrics = QFontMetrics(option->font);
+    }
+
+    value = index.data(Qt::TextAlignmentRole);
+    if (value.isValid() && !value.isNull())
+        option->displayAlignment = Qt::Alignment(value.toInt());
+
+    value = index.data(Qt::ForegroundRole);
+    if (qVariantCanConvert<QBrush>(value))
+        option->palette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value));
+
+    if (QStyleOptionViewItemV4 *v4 = qstyleoption_cast<QStyleOptionViewItemV4 *>(option)) {
+        v4->index = index;
+        QVariant value = index.data(Qt::CheckStateRole);
+        if (value.isValid() && !value.isNull()) {
+            v4->features |= QStyleOptionViewItemV2::HasCheckIndicator;
+            v4->checkState = static_cast<Qt::CheckState>(value.toInt());
+        }
+
+        value = index.data(Qt::DecorationRole);
+        if (value.isValid() && !value.isNull()) {
+            v4->features |= QStyleOptionViewItemV2::HasDecoration;
+            switch (value.type()) {
+            case QVariant::Icon: {
+                v4->icon = qvariant_cast<QIcon>(value);
+                QIcon::Mode mode;
+                if (!(option->state & QStyle::State_Enabled))
+                    mode = QIcon::Disabled;
+                else if (option->state & QStyle::State_Selected)
+                    mode = QIcon::Selected;
+                else
+                    mode = QIcon::Normal;
+                QIcon::State state = option->state & QStyle::State_Open ? QIcon::On : QIcon::Off;
+                v4->decorationSize = v4->icon.actualSize(option->decorationSize, mode, state);
+                break;
+            }
+            case QVariant::Color: {
+                QPixmap pixmap(option->decorationSize);
+                pixmap.fill(qvariant_cast<QColor>(value));
+                v4->icon = QIcon(pixmap);
+                break;
+            }
+            case QVariant::Image: {
+                QImage image = qvariant_cast<QImage>(value);
+                v4->icon = QIcon(QPixmap::fromImage(image));
+                v4->decorationSize = image.size();
+                break;
+            }
+            case QVariant::Pixmap: {
+                QPixmap pixmap = qvariant_cast<QPixmap>(value);
+                v4->icon = QIcon(pixmap);
+                v4->decorationSize = pixmap.size();
+                break;
+            }
+            default:
+                break;
+            }
+        }
+
+        value = index.data(Qt::DisplayRole);
+        if (value.isValid() && !value.isNull()) {
+            v4->features |= QStyleOptionViewItemV2::HasDisplay;
+            v4->text = displayText(value, v4->locale);
+        }
+
+        v4->backgroundBrush = qvariant_cast<QBrush>(index.data(Qt::BackgroundRole));
+    }
+}
+
+/*!
+    Renders the delegate using the given \a painter and style \a option for
+    the item specified by \a index.
+
+    This function paints the item using the view's QStyle.
+
+    When reimplementing paint in a subclass. Use the initStyleOption()
+    to set up the \a option in the same way as the
+    QStyledItemDelegate; the option will always be an instance of
+    QStyleOptionViewItemV4. Please see its class description for
+    information on its contents.
+
+    Whenever possible, use the \a option while painting.
+    Especially its \l{QStyleOption::}{rect} variable to decide
+    where to draw and its \l{QStyleOption::}{state} to determine
+    if it is enabled or selected.
+
+    After painting, you should ensure that the painter is returned to
+    its the state it was supplied in when this function was called.
+    For example, it may be useful to call QPainter::save() before
+    painting and QPainter::restore() afterwards.
+
+    \sa QItemDelegate::paint(), QStyle::drawControl(), QStyle::CE_ItemViewItem
+*/
+void QStyledItemDelegate::paint(QPainter *painter,
+        const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+    Q_ASSERT(index.isValid());
+
+    QStyleOptionViewItemV4 opt = option;
+    initStyleOption(&opt, index);
+
+    const QWidget *widget = QStyledItemDelegatePrivate::widget(option);
+    QStyle *style = widget ? widget->style() : QApplication::style();
+    style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
+}
+
+/*!
+    Returns the size needed by the delegate to display the item
+    specified by \a index, taking into account the style information
+    provided by \a option.
+
+    This function uses the view's QStyle to determine the size of the
+    item.
+
+    \sa QStyle::sizeFromContents(), QStyle::CT_ItemViewItem
+*/
+QSize QStyledItemDelegate::sizeHint(const QStyleOptionViewItem &option,
+                                   const QModelIndex &index) const
+{
+    QVariant value = index.data(Qt::SizeHintRole);
+    if (value.isValid())
+        return qvariant_cast<QSize>(value);
+
+    QStyleOptionViewItemV4 opt = option;
+    initStyleOption(&opt, index);
+    const QWidget *widget = QStyledItemDelegatePrivate::widget(option);
+    QStyle *style = widget ? widget->style() : QApplication::style();
+    return style->sizeFromContents(QStyle::CT_ItemViewItem, &opt, QSize(), widget);
+}
+
+/*!
+    Returns the widget used to edit the item specified by \a index
+    for editing. The \a parent widget and style \a option are used to
+    control how the editor widget appears.
+
+    \sa QAbstractItemDelegate::createEditor()
+*/
+QWidget *QStyledItemDelegate::createEditor(QWidget *parent,
+                                     const QStyleOptionViewItem &,
+                                     const QModelIndex &index) const
+{
+    Q_D(const QStyledItemDelegate);
+    if (!index.isValid())
+        return 0;
+    QVariant::Type t = static_cast<QVariant::Type>(index.data(Qt::EditRole).userType());
+    return d->editorFactory()->createEditor(t, parent);
+}
+
+/*!
+    Sets the data to be displayed and edited by the \a editor from the
+    data model item specified by the model \a index.
+
+    The default implementation stores the data in the \a editor
+    widget's \l {Qt's Property System} {user property}.
+
+    \sa QMetaProperty::isUser()
+*/
+void QStyledItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
+{
+#ifdef QT_NO_PROPERTIES
+    Q_UNUSED(editor);
+    Q_UNUSED(index);
+#else
+    Q_D(const QStyledItemDelegate);
+    QVariant v = index.data(Qt::EditRole);
+    QByteArray n = editor->metaObject()->userProperty().name();
+
+    // ### Qt 5: remove
+    // A work-around for missing "USER true" in qdatetimeedit.h for
+    // QTimeEdit's time property and QDateEdit's date property.
+    // It only triggers if the default user property "dateTime" is
+    // reported for QTimeEdit and QDateEdit.
+    if (n == "dateTime") {
+        if (editor->inherits("QTimeEdit"))
+            n = "time";
+        else if (editor->inherits("QDateEdit"))
+            n = "date";
+    }
+
+    // ### Qt 5: give QComboBox a USER property
+    if (n.isEmpty() && editor->inherits("QComboBox"))
+        n = d->editorFactory()->valuePropertyName(static_cast<QVariant::Type>(v.userType()));
+    if (!n.isEmpty()) {
+        if (!v.isValid())
+            v = QVariant(editor->property(n).userType(), (const void *)0);
+        editor->setProperty(n, v);
+    }
+#endif
+}
+
+/*!
+    Gets data from the \a editor widget and stores it in the specified
+    \a model at the item \a index.
+
+    The default implementation gets the value to be stored in the data
+    model from the \a editor widget's \l {Qt's Property System} {user
+    property}.
+
+    \sa QMetaProperty::isUser()
+*/
+void QStyledItemDelegate::setModelData(QWidget *editor,
+                                 QAbstractItemModel *model,
+                                 const QModelIndex &index) const
+{
+#ifdef QT_NO_PROPERTIES
+    Q_UNUSED(model);
+    Q_UNUSED(editor);
+    Q_UNUSED(index);
+#else
+    Q_D(const QStyledItemDelegate);
+    Q_ASSERT(model);
+    Q_ASSERT(editor);
+    QByteArray n = editor->metaObject()->userProperty().name();
+    if (n.isEmpty())
+        n = d->editorFactory()->valuePropertyName(
+            static_cast<QVariant::Type>(model->data(index, Qt::EditRole).userType()));
+    if (!n.isEmpty())
+        model->setData(index, editor->property(n), Qt::EditRole);
+#endif
+}
+
+/*!
+    Updates the \a editor for the item specified by \a index
+    according to the style \a option given.
+*/
+void QStyledItemDelegate::updateEditorGeometry(QWidget *editor,
+                                         const QStyleOptionViewItem &option,
+                                         const QModelIndex &index) const
+{
+    if (!editor)
+        return;
+    Q_ASSERT(index.isValid());
+    const QWidget *widget = QStyledItemDelegatePrivate::widget(option);
+
+    QStyleOptionViewItemV4 opt = option;
+    initStyleOption(&opt, index);
+    // let the editor take up all available space 
+    //if the editor is not a QLineEdit
+    //or it is in a QTableView 
+#if !defined(QT_NO_TABLEVIEW) && !defined(QT_NO_LINEEDIT)
+    if (qobject_cast<QExpandingLineEdit*>(editor) && !qobject_cast<const QTableView*>(widget))
+        opt.showDecorationSelected = editor->style()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, 0, editor);
+    else
+#endif
+        opt.showDecorationSelected = true;
+
+    QStyle *style = widget ? widget->style() : QApplication::style();
+    QRect geom = style->subElementRect(QStyle::SE_ItemViewItemText, &opt, widget);
+    if ( editor->layoutDirection() == Qt::RightToLeft) {
+        const int delta = qSmartMinSize(editor).width() - geom.width();
+        if (delta > 0) {
+            //we need to widen the geometry
+            geom.adjust(-delta, 0, 0, 0);
+        }
+    }
+
+    editor->setGeometry(geom);
+}
+
+/*!
+  Returns the editor factory used by the item delegate.
+  If no editor factory is set, the function will return null.
+
+  \sa setItemEditorFactory()
+*/
+QItemEditorFactory *QStyledItemDelegate::itemEditorFactory() const
+{
+    Q_D(const QStyledItemDelegate);
+    return d->factory;
+}
+
+/*!
+  Sets the editor factory to be used by the item delegate to be the \a factory
+  specified. If no editor factory is set, the item delegate will use the
+  default editor factory.
+
+  \sa itemEditorFactory()
+*/
+void QStyledItemDelegate::setItemEditorFactory(QItemEditorFactory *factory)
+{
+    Q_D(QStyledItemDelegate);
+    d->factory = factory;
+}
+
+
+/*!
+    \fn bool QStyledItemDelegate::eventFilter(QObject *editor, QEvent *event)
+
+    Returns true if the given \a editor is a valid QWidget and the
+    given \a event is handled; otherwise returns false. The following
+    key press events are handled by default:
+
+    \list
+        \o \gui Tab
+        \o \gui Backtab
+        \o \gui Enter
+        \o \gui Return
+        \o \gui Esc
+    \endlist
+
+    In the case of \gui Tab, \gui Backtab, \gui Enter and \gui Return
+    key press events, the \a editor's data is comitted to the model
+    and the editor is closed. If the \a event is a \gui Tab key press
+    the view will open an editor on the next item in the
+    view. Likewise, if the \a event is a \gui Backtab key press the
+    view will open an editor on the \e previous item in the view.
+
+    If the event is a \gui Esc key press event, the \a editor is
+    closed \e without committing its data.
+
+    \sa commitData(), closeEditor()
+*/
+bool QStyledItemDelegate::eventFilter(QObject *object, QEvent *event)
+{
+    QWidget *editor = qobject_cast<QWidget*>(object);
+    if (!editor)
+        return false;
+    if (event->type() == QEvent::KeyPress) {
+        switch (static_cast<QKeyEvent *>(event)->key()) {
+        case Qt::Key_Tab:
+            emit commitData(editor);
+            emit closeEditor(editor, QAbstractItemDelegate::EditNextItem);
+            return true;
+        case Qt::Key_Backtab:
+            emit commitData(editor);
+            emit closeEditor(editor, QAbstractItemDelegate::EditPreviousItem);
+            return true;
+        case Qt::Key_Enter:
+        case Qt::Key_Return:
+#ifndef QT_NO_TEXTEDIT
+            if (qobject_cast<QTextEdit *>(editor) || qobject_cast<QPlainTextEdit *>(editor))
+                return false; // don't filter enter key events for QTextEdit
+            // We want the editor to be able to process the key press
+            // before committing the data (e.g. so it can do
+            // validation/fixup of the input).
+#endif // QT_NO_TEXTEDIT
+#ifndef QT_NO_LINEEDIT
+            if (QLineEdit *e = qobject_cast<QLineEdit*>(editor))
+                if (!e->hasAcceptableInput())
+                    return false;
+#endif // QT_NO_LINEEDIT
+            QMetaObject::invokeMethod(this, "_q_commitDataAndCloseEditor",
+                                      Qt::QueuedConnection, Q_ARG(QWidget*, editor));
+            return false;
+        case Qt::Key_Escape:
+            // don't commit data
+            emit closeEditor(editor, QAbstractItemDelegate::RevertModelCache);
+            break;
+        default:
+            return false;
+        }
+        if (editor->parentWidget())
+            editor->parentWidget()->setFocus();
+        return true;
+    } else if (event->type() == QEvent::FocusOut || (event->type() == QEvent::Hide && editor->isWindow())) {
+        //the Hide event will take care of he editors that are in fact complete dialogs
+        if (!editor->isActiveWindow() || (QApplication::focusWidget() != editor)) {
+            QWidget *w = QApplication::focusWidget();
+            while (w) { // don't worry about focus changes internally in the editor
+                if (w == editor)
+                    return false;
+                w = w->parentWidget();
+            }
+#ifndef QT_NO_DRAGANDDROP
+            // The window may lose focus during an drag operation.
+            // i.e when dragging involves the taskbar on Windows.
+            if (QDragManager::self() && QDragManager::self()->object != 0)
+                return false;
+#endif
+
+            emit commitData(editor);
+            emit closeEditor(editor, NoHint);
+        }
+    } else if (event->type() == QEvent::ShortcutOverride) {
+        if (static_cast<QKeyEvent*>(event)->key() == Qt::Key_Escape) {
+            event->accept();
+            return true;
+        }
+    }
+    return false;
+}
+
+/*!
+  \reimp
+*/
+bool QStyledItemDelegate::editorEvent(QEvent *event,
+                                QAbstractItemModel *model,
+                                const QStyleOptionViewItem &option,
+                                const QModelIndex &index)
+{
+    Q_ASSERT(event);
+    Q_ASSERT(model);
+
+    // make sure that the item is checkable
+    Qt::ItemFlags flags = model->flags(index);
+    if (!(flags & Qt::ItemIsUserCheckable) || !(option.state & QStyle::State_Enabled)
+        || !(flags & Qt::ItemIsEnabled))
+        return false;
+
+    // make sure that we have a check state
+    QVariant value = index.data(Qt::CheckStateRole);
+    if (!value.isValid())
+        return false;
+
+    const QWidget *widget = QStyledItemDelegatePrivate::widget(option);
+    QStyle *style = widget ? widget->style() : QApplication::style();
+
+    // make sure that we have the right event type
+    if ((event->type() == QEvent::MouseButtonRelease)
+        || (event->type() == QEvent::MouseButtonDblClick)) {
+        QStyleOptionViewItemV4 viewOpt(option);
+        initStyleOption(&viewOpt, index);
+        QRect checkRect = style->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &viewOpt, widget);
+        QMouseEvent *me = static_cast<QMouseEvent*>(event);
+        if (me->button() != Qt::LeftButton || !checkRect.contains(me->pos()))
+            return false;
+
+        // eat the double click events inside the check rect
+        if (event->type() == QEvent::MouseButtonDblClick)
+            return true;
+
+    } else if (event->type() == QEvent::KeyPress) {
+        if (static_cast<QKeyEvent*>(event)->key() != Qt::Key_Space
+         && static_cast<QKeyEvent*>(event)->key() != Qt::Key_Select)
+            return false;
+    } else {
+        return false;
+    }
+
+    Qt::CheckState state;
+    if ( flags & Qt::ItemIsTristate ) {
+        state = static_cast<Qt::CheckState>( (value.toInt() + 1) % 3 );
+    } else {
+        state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
+                            ? Qt::Unchecked : Qt::Checked);
+    }
+    return model->setData(index, state, Qt::CheckStateRole);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qstyleditemdelegate.cpp"
+
+#endif // QT_NO_ITEMVIEWS