src/gui/itemviews/qstyleditemdelegate.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    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 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    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 
       
    78 QT_BEGIN_NAMESPACE
       
    79 
       
    80 class QStyledItemDelegatePrivate : public QObjectPrivate
       
    81 {
       
    82     Q_DECLARE_PUBLIC(QStyledItemDelegate)
       
    83 
       
    84 public:
       
    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 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 */
       
   247 QStyledItemDelegate::QStyledItemDelegate(QObject *parent)
       
   248     : QAbstractItemDelegate(*new QStyledItemDelegatePrivate(), parent)
       
   249 {
       
   250 }
       
   251 
       
   252 /*!
       
   253     Destroys the item delegate.
       
   254 */
       
   255 QStyledItemDelegate::~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 */
       
   267 QString 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 */
       
   315 void 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 */
       
   414 void 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 */
       
   437 QSize 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 */
       
   458 QWidget *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 */
       
   478 void 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 */
       
   521 void 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 */
       
   546 void 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 */
       
   586 QItemEditorFactory *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 */
       
   599 void 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 */
       
   633 bool 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 */
       
   706 bool 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;
       
   751     if ( flags & Qt::ItemIsTristate ) {
       
   752         state = static_cast<Qt::CheckState>( (value.toInt() + 1) % 3 );
       
   753     } else {
       
   754         state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
       
   755                             ? Qt::Unchecked : Qt::Checked);
       
   756     }
       
   757     return model->setData(index, state, Qt::CheckStateRole);
       
   758 }
       
   759 
       
   760 QT_END_NAMESPACE
       
   761 
       
   762 #include "moc_qstyleditemdelegate.cpp"
       
   763 
       
   764 #endif // QT_NO_ITEMVIEWS