summaryrefslogtreecommitdiffstats
path: root/src/gui/itemviews/qitemdelegate.cpp
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2009-03-23 09:18:55 (GMT)
committerSimon Hausmann <simon.hausmann@nokia.com>2009-03-23 09:18:55 (GMT)
commite5fcad302d86d316390c6b0f62759a067313e8a9 (patch)
treec2afbf6f1066b6ce261f14341cf6d310e5595bc1 /src/gui/itemviews/qitemdelegate.cpp
downloadQt-e5fcad302d86d316390c6b0f62759a067313e8a9.zip
Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz
Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.bz2
Long live Qt 4.5!
Diffstat (limited to 'src/gui/itemviews/qitemdelegate.cpp')
-rw-r--r--src/gui/itemviews/qitemdelegate.cpp1337
1 files changed, 1337 insertions, 0 deletions
diff --git a/src/gui/itemviews/qitemdelegate.cpp b/src/gui/itemviews/qitemdelegate.cpp
new file mode 100644
index 0000000..bf9b5c5
--- /dev/null
+++ b/src/gui/itemviews/qitemdelegate.cpp
@@ -0,0 +1,1337 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qitemdelegate.h"
+
+#ifndef QT_NO_ITEMVIEWS
+#include <qabstractitemmodel.h>
+#include <qapplication.h>
+#include <qbrush.h>
+#include <qlineedit.h>
+#include <qtextedit.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 <qmetaobject.h>
+#include <qtextlayout.h>
+#include <private/qobject_p.h>
+#include <private/qdnd_p.h>
+#include <private/qtextengine_p.h>
+#include <qdebug.h>
+#include <qlocale.h>
+#include <qdialog.h>
+
+#include <limits.h>
+
+#ifndef DBL_DIG
+# define DBL_DIG 10
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QItemDelegatePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QItemDelegate)
+
+public:
+ QItemDelegatePrivate() : f(0), clipPainting(true) {}
+
+ inline const QItemEditorFactory *editorFactory() const
+ { return f ? f : QItemEditorFactory::defaultFactory(); }
+
+ inline QIcon::Mode iconMode(QStyle::State state) const
+ {
+ if (!(state & QStyle::State_Enabled)) return QIcon::Disabled;
+ if (state & QStyle::State_Selected) return QIcon::Selected;
+ return QIcon::Normal;
+ }
+
+ inline QIcon::State iconState(QStyle::State state) const
+ { return state & QStyle::State_Open ? QIcon::On : QIcon::Off; }
+
+ inline static QString replaceNewLine(QString text)
+ {
+ const QChar nl = QLatin1Char('\n');
+ for (int i = 0; i < text.count(); ++i)
+ if (text.at(i) == nl)
+ text[i] = QChar::LineSeparator;
+ return text;
+ }
+
+ static QString valueToText(const QVariant &value, const QStyleOptionViewItemV4 &option);
+
+ void _q_commitDataAndCloseEditor(QWidget *editor);
+
+ QItemEditorFactory *f;
+ bool clipPainting;
+
+ QRect textLayoutBounds(const QStyleOptionViewItemV2 &options) const;
+ QSizeF doTextLayout(int lineWidth) const;
+ mutable QTextLayout textLayout;
+ mutable QTextOption textOption;
+
+ const QWidget *widget(const QStyleOptionViewItem &option) const
+ {
+ if (const QStyleOptionViewItemV3 *v3 = qstyleoption_cast<const QStyleOptionViewItemV3 *>(&option))
+ return v3->widget;
+
+ return 0;
+ }
+
+ // ### temporary hack until we have QStandardItemDelegate
+ mutable struct Icon {
+ QIcon icon;
+ QIcon::Mode mode;
+ QIcon::State state;
+ } tmp;
+};
+
+void QItemDelegatePrivate::_q_commitDataAndCloseEditor(QWidget *editor)
+{
+ Q_Q(QItemDelegate);
+ emit q->commitData(editor);
+ emit q->closeEditor(editor, QAbstractItemDelegate::SubmitModelCache);
+}
+
+QRect QItemDelegatePrivate::textLayoutBounds(const QStyleOptionViewItemV2 &option) const
+{
+ QRect rect = option.rect;
+ const bool wrapText = option.features & QStyleOptionViewItemV2::WrapText;
+ switch (option.decorationPosition) {
+ case QStyleOptionViewItem::Left:
+ case QStyleOptionViewItem::Right:
+ rect.setWidth(wrapText && rect.isValid() ? rect.width() : (QFIXED_MAX));
+ break;
+ case QStyleOptionViewItem::Top:
+ case QStyleOptionViewItem::Bottom:
+ rect.setWidth(wrapText ? option.decorationSize.width() : (QFIXED_MAX));
+ break;
+ }
+
+ return rect;
+}
+
+QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const
+{
+ qreal height = 0;
+ qreal widthUsed = 0;
+ textLayout.beginLayout();
+ while (true) {
+ QTextLine line = textLayout.createLine();
+ if (!line.isValid())
+ break;
+ line.setLineWidth(lineWidth);
+ line.setPosition(QPointF(0, height));
+ height += line.height();
+ widthUsed = qMax(widthUsed, line.naturalTextWidth());
+ }
+ textLayout.endLayout();
+ return QSizeF(widthUsed, height);
+}
+
+/*!
+ \class QItemDelegate
+
+ \brief The QItemDelegate class provides display and editing facilities for
+ data items from a model.
+
+ \ingroup model-view
+ \mainclass
+
+ QItemDelegate can be used to provide custom display features and editor
+ widgets for item views based on QAbstractItemView subclasses. Using a
+ delegate for this purpose allows the display and editing mechanisms to be
+ customized and developed independently from the model and view.
+
+ The QItemDelegate class is one of the \l{Model/View Classes} and
+ is part of Qt's \l{Model/View Programming}{model/view framework}.
+ Note that QStyledItemDelegate has taken over the job of drawing
+ Qt's item views. We recommend the use of QStyledItemDelegate when
+ creating new delegates.
+
+ When displaying items from a custom model in a standard view, it is
+ often sufficient to simply ensure that the model returns appropriate
+ data for each of the \l{Qt::ItemDataRole}{roles} that determine the
+ appearance of items in views. The default delegate used by Qt's
+ standard views uses this role information to display items in most
+ of the common forms expected by users. However, it is sometimes
+ necessary to have even more control over the appearance of items than
+ the default delegate can provide.
+
+ This class provides default implementations of the functions for
+ painting item data in a view and editing data from item models.
+ Default implementations of the paint() and sizeHint() virtual
+ functions, defined in QAbstractItemDelegate, are provided to
+ ensure that the delegate implements the correct basic behavior
+ expected by views. You can reimplement these functions in
+ subclasses to customize the appearance of items.
+
+ When editing data in an item view, QItemDelegate provides an
+ editor widget, which is a widget that is placed on top of the view
+ while editing takes place. Editors are created with a
+ QItemEditorFactory; a default static instance provided by
+ QItemEditorFactory is installed on all item delagates. 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 Qt::EditRole that is edited.
+
+ Only the standard editing functions for widget-based delegates are
+ reimplemented here:
+
+ \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 closeEditor() signal indicates that the user has completed editing the data,
+ and that the editor widget can be destroyed.
+
+ \section1 Standard Roles and Data Types
+
+ The default delegate used by the standard views supplied with Qt
+ associates each standard role (defined by Qt::ItemDataRole) with certain
+ data types. Models that return data in these types can influence the
+ appearance of the delegate as described in the following table.
+
+ \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
+
+ If the default delegate does not allow the level of customization that
+ you need, either for display purposes or for editing data, it is possible to
+ subclass QItemDelegate to implement the desired behavior.
+
+ \section1 Subclassing
+
+ When subclassing QItemDelegate to create a delegate that displays items
+ using a custom renderer, it is important to ensure that the delegate can
+ render items suitably for all the required states; e.g. selected,
+ disabled, checked. The documentation for the paint() function contains
+ some hints to show how this can be achieved.
+
+ You can provide custom editors by using a QItemEditorFactory. The
+ \l{Color Editor Factory Example} shows how a custom editor can be
+ made available to delegates with the default item editor
+ factory. This way, there is no need to subclass QItemDelegate. An
+ alternative is to reimplement createEditor(), setEditorData(),
+ setModelData(), and updateEditorGeometry(). This process is
+ described in the \l{Spin Box Delegate Example}.
+
+ \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.
+
+ \sa {Delegate Classes}, QStyledItemDelegate, QAbstractItemDelegate,
+ {Spin Box Delegate Example}, {Settings Editor Example},
+ {Icons Example}
+*/
+
+/*!
+ Constructs an item delegate with the given \a parent.
+*/
+
+QItemDelegate::QItemDelegate(QObject *parent)
+ : QAbstractItemDelegate(*new QItemDelegatePrivate(), parent)
+{
+
+}
+
+/*!
+ Destroys the item delegate.
+*/
+
+QItemDelegate::~QItemDelegate()
+{
+}
+
+/*!
+ \property QItemDelegate::clipping
+ \brief if the delegate should clip the paint events
+ \since 4.2
+
+ This property will set the paint clip to the size of the item.
+ The default value is on. It is useful for cases such
+ as when images are larger than the size of the item.
+*/
+
+bool QItemDelegate::hasClipping() const
+{
+ Q_D(const QItemDelegate);
+ return d->clipPainting;
+}
+
+void QItemDelegate::setClipping(bool clip)
+{
+ Q_D(QItemDelegate);
+ d->clipPainting = clip;
+}
+
+QString QItemDelegatePrivate::valueToText(const QVariant &value, const QStyleOptionViewItemV4 &option)
+{
+ QString text;
+ switch (value.type()) {
+ case QVariant::Double:
+ text = option.locale.toString(value.toDouble(), 'g', DBL_DIG);
+ break;
+ case QVariant::Int:
+ case QVariant::LongLong:
+ text = option.locale.toString(value.toLongLong());
+ break;
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ text = option.locale.toString(value.toULongLong());
+ break;
+ case QVariant::Date:
+ text = option.locale.toString(value.toDate(), QLocale::ShortFormat);
+ break;
+ case QVariant::Time:
+ text = option.locale.toString(value.toTime(), QLocale::ShortFormat);
+ break;
+ case QVariant::DateTime:
+ text = option.locale.toString(value.toDateTime().date(), QLocale::ShortFormat);
+ text += QLatin1Char(' ');
+ text += option.locale.toString(value.toDateTime().time(), QLocale::ShortFormat);
+ break;
+ default:
+ text = replaceNewLine(value.toString());
+ break;
+ }
+ return text;
+}
+
+/*!
+ Renders the delegate using the given \a painter and style \a option for
+ the item specified by \a index.
+
+ When reimplementing this function in a subclass, you should update the area
+ held by the option's \l{QStyleOption::rect}{rect} variable, using the
+ option's \l{QStyleOption::state}{state} variable to determine the state of
+ the item to be displayed, and adjust the way it is painted accordingly.
+
+ For example, a selected item may need to be displayed differently to
+ unselected items, as shown in the following code:
+
+ \snippet examples/itemviews/pixelator/pixeldelegate.cpp 2
+ \dots
+
+ 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 QStyle::State
+*/
+void QItemDelegate::paint(QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ Q_D(const QItemDelegate);
+ Q_ASSERT(index.isValid());
+
+ QStyleOptionViewItemV4 opt = setOptions(index, option);
+
+ const QStyleOptionViewItemV2 *v2 = qstyleoption_cast<const QStyleOptionViewItemV2 *>(&option);
+ opt.features = v2 ? v2->features
+ : QStyleOptionViewItemV2::ViewItemFeatures(QStyleOptionViewItemV2::None);
+ const QStyleOptionViewItemV3 *v3 = qstyleoption_cast<const QStyleOptionViewItemV3 *>(&option);
+ opt.locale = v3 ? v3->locale : QLocale();
+ opt.widget = v3 ? v3->widget : 0;
+
+ // prepare
+ painter->save();
+ if (d->clipPainting)
+ painter->setClipRect(opt.rect);
+
+ // get the data and the rectangles
+
+ QVariant value;
+
+ QPixmap pixmap;
+ QRect decorationRect;
+ value = index.data(Qt::DecorationRole);
+ if (value.isValid()) {
+ // ### we need the pixmap to call the virtual function
+ pixmap = decoration(opt, value);
+ if (value.type() == QVariant::Icon) {
+ d->tmp.icon = qvariant_cast<QIcon>(value);
+ d->tmp.mode = d->iconMode(option.state);
+ d->tmp.state = d->iconState(option.state);
+ const QSize size = d->tmp.icon.actualSize(option.decorationSize,
+ d->tmp.mode, d->tmp.state);
+ decorationRect = QRect(QPoint(0, 0), size);
+ } else {
+ d->tmp.icon = QIcon();
+ decorationRect = QRect(QPoint(0, 0), pixmap.size());
+ }
+ } else {
+ d->tmp.icon = QIcon();
+ decorationRect = QRect();
+ }
+
+ QString text;
+ QRect displayRect;
+ value = index.data(Qt::DisplayRole);
+ if (value.isValid() && !value.isNull()) {
+ text = QItemDelegatePrivate::valueToText(value, opt);
+ displayRect = textRectangle(painter, d->textLayoutBounds(opt), opt.font, text);
+ }
+
+ QRect checkRect;
+ Qt::CheckState checkState = Qt::Unchecked;
+ value = index.data(Qt::CheckStateRole);
+ if (value.isValid()) {
+ checkState = static_cast<Qt::CheckState>(value.toInt());
+ checkRect = check(opt, opt.rect, value);
+ }
+
+ // do the layout
+
+ doLayout(opt, &checkRect, &decorationRect, &displayRect, false);
+
+ // draw the item
+
+ drawBackground(painter, opt, index);
+ drawCheck(painter, opt, checkRect, checkState);
+ drawDecoration(painter, opt, decorationRect, pixmap);
+ drawDisplay(painter, opt, displayRect, text);
+ drawFocus(painter, opt, displayRect);
+
+ // done
+ painter->restore();
+}
+
+/*!
+ 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.
+
+ When reimplementing this function, note that in case of text
+ items, QItemDelegate adds a margin (i.e. 2 *
+ QStyle::PM_FocusFrameHMargin) to the length of the text.
+*/
+
+QSize QItemDelegate::sizeHint(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ QVariant value = index.data(Qt::SizeHintRole);
+ if (value.isValid())
+ return qvariant_cast<QSize>(value);
+ QRect decorationRect = rect(option, index, Qt::DecorationRole);
+ QRect displayRect = rect(option, index, Qt::DisplayRole);
+ QRect checkRect = rect(option, index, Qt::CheckStateRole);
+
+ doLayout(option, &checkRect, &decorationRect, &displayRect, true);
+
+ return (decorationRect|displayRect|checkRect).size();
+}
+
+/*!
+ 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 *QItemDelegate::createEditor(QWidget *parent,
+ const QStyleOptionViewItem &,
+ const QModelIndex &index) const
+{
+ Q_D(const QItemDelegate);
+ if (!index.isValid())
+ return 0;
+ QVariant::Type t = static_cast<QVariant::Type>(index.data(Qt::EditRole).userType());
+ const QItemEditorFactory *factory = d->f;
+ if (factory == 0)
+ factory = QItemEditorFactory::defaultFactory();
+ return factory->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 QItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
+{
+#ifdef QT_NO_PROPERTIES
+ Q_UNUSED(editor);
+ Q_UNUSED(index);
+#else
+ Q_D(const QItemDelegate);
+ 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 drom 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 QItemDelegate::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 QItemDelegate);
+ 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 QItemDelegate::updateEditorGeometry(QWidget *editor,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ if (!editor)
+ return;
+ Q_ASSERT(index.isValid());
+ QPixmap pixmap = decoration(option, index.data(Qt::DecorationRole));
+ QString text = QItemDelegatePrivate::replaceNewLine(index.data(Qt::DisplayRole).toString());
+ QRect pixmapRect = QRect(QPoint(0, 0), option.decorationSize).intersected(pixmap.rect());
+ QRect textRect = textRectangle(0, option.rect, option.font, text);
+ QRect checkRect = check(option, textRect, index.data(Qt::CheckStateRole));
+ QStyleOptionViewItem opt = option;
+ opt.showDecorationSelected = true; // let the editor take up all available space
+ doLayout(opt, &checkRect, &pixmapRect, &textRect, false);
+ editor->setGeometry(textRect);
+}
+
+/*!
+ Returns the editor factory used by the item delegate.
+ If no editor factory is set, the function will return null.
+
+ \sa setItemEditorFactory()
+*/
+QItemEditorFactory *QItemDelegate::itemEditorFactory() const
+{
+ Q_D(const QItemDelegate);
+ return d->f;
+}
+
+/*!
+ 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 QItemDelegate::setItemEditorFactory(QItemEditorFactory *factory)
+{
+ Q_D(QItemDelegate);
+ d->f = factory;
+}
+
+/*!
+ Renders the item view \a text within the rectangle specified by \a rect
+ using the given \a painter and style \a option.
+*/
+
+void QItemDelegate::drawDisplay(QPainter *painter, const QStyleOptionViewItem &option,
+ const QRect &rect, const QString &text) const
+{
+ Q_D(const QItemDelegate);
+
+ QPen pen = painter->pen();
+ QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
+ ? QPalette::Normal : QPalette::Disabled;
+ if (cg == QPalette::Normal && !(option.state & QStyle::State_Active))
+ cg = QPalette::Inactive;
+ if (option.state & QStyle::State_Selected) {
+ painter->fillRect(rect, option.palette.brush(cg, QPalette::Highlight));
+ painter->setPen(option.palette.color(cg, QPalette::HighlightedText));
+ } else {
+ painter->setPen(option.palette.color(cg, QPalette::Text));
+ }
+
+ if (text.isEmpty())
+ return;
+
+ if (option.state & QStyle::State_Editing) {
+ painter->save();
+ painter->setPen(option.palette.color(cg, QPalette::Text));
+ painter->drawRect(rect.adjusted(0, 0, -1, -1));
+ painter->restore();
+ }
+
+ const QStyleOptionViewItemV4 opt = option;
+
+ const QWidget *widget = d->widget(option);
+ QStyle *style = widget ? widget->style() : QApplication::style();
+ const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, widget) + 1;
+ QRect textRect = rect.adjusted(textMargin, 0, -textMargin, 0); // remove width padding
+ const bool wrapText = opt.features & QStyleOptionViewItemV2::WrapText;
+ d->textOption.setWrapMode(wrapText ? QTextOption::WordWrap : QTextOption::ManualWrap);
+ d->textOption.setTextDirection(option.direction);
+ d->textOption.setAlignment(QStyle::visualAlignment(option.direction, option.displayAlignment));
+ d->textLayout.setTextOption(d->textOption);
+ d->textLayout.setFont(option.font);
+ d->textLayout.setText(QItemDelegatePrivate::replaceNewLine(text));
+
+ QSizeF textLayoutSize = d->doTextLayout(textRect.width());
+
+ if (textRect.width() < textLayoutSize.width()
+ || textRect.height() < textLayoutSize.height()) {
+ QString elided;
+ int start = 0;
+ int end = text.indexOf(QChar::LineSeparator, start);
+ if (end == -1) {
+ elided += option.fontMetrics.elidedText(text, option.textElideMode, textRect.width());
+ } else {
+ while (end != -1) {
+ elided += option.fontMetrics.elidedText(text.mid(start, end - start),
+ option.textElideMode, textRect.width());
+ elided += QChar::LineSeparator;
+ start = end + 1;
+ end = text.indexOf(QChar::LineSeparator, start);
+ }
+ //let's add the last line (after the last QChar::LineSeparator)
+ elided += option.fontMetrics.elidedText(text.mid(start),
+ option.textElideMode, textRect.width());
+ if (end != -1)
+ elided += QChar::LineSeparator;
+ }
+ d->textLayout.setText(elided);
+ textLayoutSize = d->doTextLayout(textRect.width());
+ }
+
+ const QSize layoutSize(textRect.width(), int(textLayoutSize.height()));
+ const QRect layoutRect = QStyle::alignedRect(option.direction, option.displayAlignment,
+ layoutSize, textRect);
+ // if we still overflow even after eliding the text, enable clipping
+ if (!hasClipping() && (textRect.width() < textLayoutSize.width()
+ || textRect.height() < textLayoutSize.height())) {
+ painter->save();
+ painter->setClipRect(layoutRect);
+ d->textLayout.draw(painter, layoutRect.topLeft(), QVector<QTextLayout::FormatRange>(), layoutRect);
+ painter->restore();
+ } else {
+ d->textLayout.draw(painter, layoutRect.topLeft(), QVector<QTextLayout::FormatRange>(), layoutRect);
+ }
+}
+
+/*!
+ Renders the decoration \a pixmap within the rectangle specified by
+ \a rect using the given \a painter and style \a option.
+*/
+void QItemDelegate::drawDecoration(QPainter *painter, const QStyleOptionViewItem &option,
+ const QRect &rect, const QPixmap &pixmap) const
+{
+ Q_D(const QItemDelegate);
+ // if we have an icon, we ignore the pixmap
+ if (!d->tmp.icon.isNull()) {
+ d->tmp.icon.paint(painter, rect, option.decorationAlignment,
+ d->tmp.mode, d->tmp.state);
+ return;
+ }
+
+ if (pixmap.isNull() || !rect.isValid())
+ return;
+ QPoint p = QStyle::alignedRect(option.direction, option.decorationAlignment,
+ pixmap.size(), rect).topLeft();
+ if (option.state & QStyle::State_Selected) {
+ QPixmap *pm = selected(pixmap, option.palette, option.state & QStyle::State_Enabled);
+ painter->drawPixmap(p, *pm);
+ } else {
+ painter->drawPixmap(p, pixmap);
+ }
+}
+
+/*!
+ Renders the region within the rectangle specified by \a rect, indicating
+ that it has the focus, using the given \a painter and style \a option.
+*/
+
+void QItemDelegate::drawFocus(QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QRect &rect) const
+{
+ Q_D(const QItemDelegate);
+ if ((option.state & QStyle::State_HasFocus) == 0 || !rect.isValid())
+ return;
+ QStyleOptionFocusRect o;
+ o.QStyleOption::operator=(option);
+ o.rect = rect;
+ o.state |= QStyle::State_KeyboardFocusChange;
+ o.state |= QStyle::State_Item;
+ QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled)
+ ? QPalette::Normal : QPalette::Disabled;
+ o.backgroundColor = option.palette.color(cg, (option.state & QStyle::State_Selected)
+ ? QPalette::Highlight : QPalette::Window);
+ const QWidget *widget = d->widget(option);
+ QStyle *style = widget ? widget->style() : QApplication::style();
+ style->drawPrimitive(QStyle::PE_FrameFocusRect, &o, painter, widget);
+}
+
+/*!
+ Renders a check indicator within the rectangle specified by \a
+ rect, using the given \a painter and style \a option, using the
+ given \a state.
+*/
+
+void QItemDelegate::drawCheck(QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QRect &rect, Qt::CheckState state) const
+{
+ Q_D(const QItemDelegate);
+ if (!rect.isValid())
+ return;
+
+ QStyleOptionViewItem opt(option);
+ opt.rect = rect;
+ opt.state = opt.state & ~QStyle::State_HasFocus;
+
+ switch (state) {
+ case Qt::Unchecked:
+ opt.state |= QStyle::State_Off;
+ break;
+ case Qt::PartiallyChecked:
+ opt.state |= QStyle::State_NoChange;
+ break;
+ case Qt::Checked:
+ opt.state |= QStyle::State_On;
+ break;
+ }
+
+ const QWidget *widget = d->widget(option);
+ QStyle *style = widget ? widget->style() : QApplication::style();
+ style->drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &opt, painter, widget);
+}
+
+/*!
+ \since 4.2
+
+ Renders the item background for the given \a index,
+ using the given \a painter and style \a option.
+*/
+
+void QItemDelegate::drawBackground(QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ if (option.showDecorationSelected && (option.state & QStyle::State_Selected)) {
+ QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
+ ? QPalette::Normal : QPalette::Disabled;
+ if (cg == QPalette::Normal && !(option.state & QStyle::State_Active))
+ cg = QPalette::Inactive;
+
+ painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight));
+ } else {
+ QVariant value = index.data(Qt::BackgroundRole);
+ if (qVariantCanConvert<QBrush>(value)) {
+ QPointF oldBO = painter->brushOrigin();
+ painter->setBrushOrigin(option.rect.topLeft());
+ painter->fillRect(option.rect, qvariant_cast<QBrush>(value));
+ painter->setBrushOrigin(oldBO);
+ }
+ }
+}
+
+
+/*!
+ \internal
+*/
+
+void QItemDelegate::doLayout(const QStyleOptionViewItem &option,
+ QRect *checkRect, QRect *pixmapRect, QRect *textRect,
+ bool hint) const
+{
+ Q_ASSERT(checkRect && pixmapRect && textRect);
+ Q_D(const QItemDelegate);
+ const QWidget *widget = d->widget(option);
+ QStyle *style = widget ? widget->style() : QApplication::style();
+ const bool hasCheck = checkRect->isValid();
+ const bool hasPixmap = pixmapRect->isValid();
+ const bool hasText = textRect->isValid();
+ const int textMargin = hasText ? style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, widget) + 1 : 0;
+ const int pixmapMargin = hasPixmap ? style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, widget) + 1 : 0;
+ const int checkMargin = hasCheck ? style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, widget) + 1 : 0;
+ int x = option.rect.left();
+ int y = option.rect.top();
+ int w, h;
+
+ textRect->adjust(-textMargin, 0, textMargin, 0); // add width padding
+ if (textRect->height() == 0 && !hasPixmap)
+ textRect->setHeight(option.fontMetrics.height());
+
+ QSize pm(0, 0);
+ if (hasPixmap) {
+ pm = pixmapRect->size();
+ pm.rwidth() += 2 * pixmapMargin;
+ }
+ if (hint) {
+ h = qMax(checkRect->height(), qMax(textRect->height(), pm.height()));
+ if (option.decorationPosition == QStyleOptionViewItem::Left
+ || option.decorationPosition == QStyleOptionViewItem::Right) {
+ w = textRect->width() + pm.width();
+ } else {
+ w = qMax(textRect->width(), pm.width());
+ }
+ } else {
+ w = option.rect.width();
+ h = option.rect.height();
+ }
+
+ int cw = 0;
+ QRect check;
+ if (hasCheck) {
+ cw = checkRect->width() + 2 * checkMargin;
+ if (hint) w += cw;
+ if (option.direction == Qt::RightToLeft) {
+ check.setRect(x + w - cw, y, cw, h);
+ } else {
+ check.setRect(x + checkMargin, y, cw, h);
+ }
+ }
+
+ // at this point w should be the *total* width
+
+ QRect display;
+ QRect decoration;
+ switch (option.decorationPosition) {
+ case QStyleOptionViewItem::Top: {
+ if (hasPixmap)
+ pm.setHeight(pm.height() + pixmapMargin); // add space
+ h = hint ? textRect->height() : h - pm.height();
+
+ if (option.direction == Qt::RightToLeft) {
+ decoration.setRect(x, y, w - cw, pm.height());
+ display.setRect(x, y + pm.height(), w - cw, h);
+ } else {
+ decoration.setRect(x + cw, y, w - cw, pm.height());
+ display.setRect(x + cw, y + pm.height(), w - cw, h);
+ }
+ break; }
+ case QStyleOptionViewItem::Bottom: {
+ if (hasText)
+ textRect->setHeight(textRect->height() + textMargin); // add space
+ h = hint ? textRect->height() + pm.height() : h;
+
+ if (option.direction == Qt::RightToLeft) {
+ display.setRect(x, y, w - cw, textRect->height());
+ decoration.setRect(x, y + textRect->height(), w - cw, h - textRect->height());
+ } else {
+ display.setRect(x + cw, y, w - cw, textRect->height());
+ decoration.setRect(x + cw, y + textRect->height(), w - cw, h - textRect->height());
+ }
+ break; }
+ case QStyleOptionViewItem::Left: {
+ if (option.direction == Qt::LeftToRight) {
+ decoration.setRect(x + cw, y, pm.width(), h);
+ display.setRect(decoration.right() + 1, y, w - pm.width() - cw, h);
+ } else {
+ display.setRect(x, y, w - pm.width() - cw, h);
+ decoration.setRect(display.right() + 1, y, pm.width(), h);
+ }
+ break; }
+ case QStyleOptionViewItem::Right: {
+ if (option.direction == Qt::LeftToRight) {
+ display.setRect(x + cw, y, w - pm.width() - cw, h);
+ decoration.setRect(display.right() + 1, y, pm.width(), h);
+ } else {
+ decoration.setRect(x, y, pm.width(), h);
+ display.setRect(decoration.right() + 1, y, w - pm.width() - cw, h);
+ }
+ break; }
+ default:
+ qWarning("doLayout: decoration position is invalid");
+ decoration = *pixmapRect;
+ break;
+ }
+
+ if (!hint) { // we only need to do the internal layout if we are going to paint
+ *checkRect = QStyle::alignedRect(option.direction, Qt::AlignCenter,
+ checkRect->size(), check);
+ *pixmapRect = QStyle::alignedRect(option.direction, option.decorationAlignment,
+ pixmapRect->size(), decoration);
+ // the text takes up all available space, unless the decoration is not shown as selected
+ if (option.showDecorationSelected)
+ *textRect = display;
+ else
+ *textRect = QStyle::alignedRect(option.direction, option.displayAlignment,
+ textRect->size().boundedTo(display.size()), display);
+ } else {
+ *checkRect = check;
+ *pixmapRect = decoration;
+ *textRect = display;
+ }
+}
+
+/*!
+ \internal
+
+ Returns the pixmap used to decorate the root of the item view.
+ The style \a option controls the appearance of the root; the \a variant
+ refers to the data associated with an item.
+*/
+
+QPixmap QItemDelegate::decoration(const QStyleOptionViewItem &option, const QVariant &variant) const
+{
+ Q_D(const QItemDelegate);
+ switch (variant.type()) {
+ case QVariant::Icon: {
+ QIcon::Mode mode = d->iconMode(option.state);
+ QIcon::State state = d->iconState(option.state);
+ return qvariant_cast<QIcon>(variant).pixmap(option.decorationSize, mode, state); }
+ case QVariant::Color: {
+ static QPixmap pixmap(option.decorationSize);
+ pixmap.fill(qvariant_cast<QColor>(variant));
+ return pixmap; }
+ default:
+ break;
+ }
+
+ return qvariant_cast<QPixmap>(variant);
+}
+
+// hacky but faster version of "QString::sprintf("%d-%d", i, enabled)"
+static QString qPixmapSerial(quint64 i, bool enabled)
+{
+ ushort arr[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', '0' + enabled };
+ ushort *ptr = &arr[16];
+
+ while (i > 0) {
+ // hey - it's our internal representation, so use the ascii character after '9'
+ // instead of 'a' for hex
+ *(--ptr) = '0' + i % 16;
+ i >>= 4;
+ }
+
+ return QString::fromUtf16(ptr, int(&arr[sizeof(arr) / sizeof(ushort)] - ptr));
+}
+
+/*!
+ \internal
+ Returns the selected version of the given \a pixmap using the given \a palette.
+ The \a enabled argument decides whether the normal or disabled highlight color of
+ the palette is used.
+*/
+QPixmap *QItemDelegate::selected(const QPixmap &pixmap, const QPalette &palette, bool enabled) const
+{
+ QString key = qPixmapSerial(qt_pixmap_id(pixmap), enabled);
+ QPixmap *pm = QPixmapCache::find(key);
+ if (!pm) {
+ QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied);
+
+ QColor color = palette.color(enabled ? QPalette::Normal : QPalette::Disabled,
+ QPalette::Highlight);
+ color.setAlphaF((qreal)0.3);
+
+ QPainter painter(&img);
+ painter.setCompositionMode(QPainter::CompositionMode_SourceAtop);
+ painter.fillRect(0, 0, img.width(), img.height(), color);
+ painter.end();
+
+ QPixmap selected = QPixmap(QPixmap::fromImage(img));
+ int n = (img.numBytes() >> 10) + 1;
+ if (QPixmapCache::cacheLimit() < n)
+ QPixmapCache::setCacheLimit(n);
+
+ QPixmapCache::insert(key, selected);
+ pm = QPixmapCache::find(key);
+ }
+ return pm;
+}
+
+/*!
+ \internal
+*/
+
+QRect QItemDelegate::rect(const QStyleOptionViewItem &option,
+ const QModelIndex &index, int role) const
+{
+ Q_D(const QItemDelegate);
+ QVariant value = index.data(role);
+ if (role == Qt::CheckStateRole)
+ return check(option, option.rect, value);
+ if (value.isValid() && !value.isNull()) {
+ switch (value.type()) {
+ case QVariant::Invalid:
+ break;
+ case QVariant::Pixmap:
+ return QRect(QPoint(0, 0), qvariant_cast<QPixmap>(value).size());
+ case QVariant::Image:
+ return QRect(QPoint(0, 0), qvariant_cast<QImage>(value).size());
+ case QVariant::Icon: {
+ QIcon::Mode mode = d->iconMode(option.state);
+ QIcon::State state = d->iconState(option.state);
+ QIcon icon = qvariant_cast<QIcon>(value);
+ QSize size = icon.actualSize(option.decorationSize, mode, state);
+ return QRect(QPoint(0, 0), size); }
+ case QVariant::Color:
+ return QRect(QPoint(0, 0), option.decorationSize);
+ case QVariant::String:
+ default: {
+ QString text = QItemDelegatePrivate::valueToText(value, option);
+ value = index.data(Qt::FontRole);
+ QFont fnt = qvariant_cast<QFont>(value).resolve(option.font);
+ return textRectangle(0, d->textLayoutBounds(option), fnt, text); }
+ }
+ }
+ return QRect();
+}
+
+/*!
+ \internal
+
+ Note that on Mac, if /usr/include/AssertMacros.h is included prior
+ to QItemDelegate, and the application is building in debug mode, the
+ check(assertion) will conflict with QItemDelegate::check.
+
+ To avoid this problem, add
+
+ #ifdef check
+ #undef check
+ #endif
+
+ after including AssertMacros.h
+*/
+QRect QItemDelegate::check(const QStyleOptionViewItem &option,
+ const QRect &bounding, const QVariant &value) const
+{
+ if (value.isValid()) {
+ Q_D(const QItemDelegate);
+ QStyleOptionButton opt;
+ opt.QStyleOption::operator=(option);
+ opt.rect = bounding;
+ const QWidget *widget = d->widget(option); // cast
+ QStyle *style = widget ? widget->style() : QApplication::style();
+ return style->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt, widget);
+ }
+ return QRect();
+}
+
+/*!
+ \internal
+*/
+QRect QItemDelegate::textRectangle(QPainter * /*painter*/, const QRect &rect,
+ const QFont &font, const QString &text) const
+{
+ Q_D(const QItemDelegate);
+ d->textOption.setWrapMode(QTextOption::WordWrap);
+ d->textLayout.setTextOption(d->textOption);
+ d->textLayout.setFont(font);
+ d->textLayout.setText(QItemDelegatePrivate::replaceNewLine(text));
+ const QSize size = d->doTextLayout(rect.width()).toSize();
+ // ###: textRectangle should take style option as argument
+ const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
+ return QRect(0, 0, size.width() + 2 * textMargin, size.height());
+}
+
+/*!
+ \fn bool QItemDelegate::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 QItemDelegate::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))
+ 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) {
+ //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
+ // Opening a modal dialog will start a new eventloop
+ // that will process the deleteLater event.
+ if (QApplication::activeModalWidget()
+ && !QApplication::activeModalWidget()->isAncestorOf(editor)
+ && qobject_cast<QDialog*>(QApplication::activeModalWidget()))
+ return false;
+ 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 QItemDelegate::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;
+
+ // make sure that we have the right event type
+ if ((event->type() == QEvent::MouseButtonRelease)
+ || (event->type() == QEvent::MouseButtonDblClick)) {
+ QRect checkRect = check(option, option.rect, Qt::Checked);
+ QRect emptyRect;
+ doLayout(option, &checkRect, &emptyRect, &emptyRect, false);
+ 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 = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
+ ? Qt::Unchecked : Qt::Checked);
+ return model->setData(index, state, Qt::CheckStateRole);
+}
+
+/*!
+ \internal
+*/
+
+QStyleOptionViewItem QItemDelegate::setOptions(const QModelIndex &index,
+ const QStyleOptionViewItem &option) const
+{
+ QStyleOptionViewItem opt = option;
+
+ // set font
+ QVariant value = index.data(Qt::FontRole);
+ if (value.isValid()){
+ opt.font = qvariant_cast<QFont>(value).resolve(opt.font);
+ opt.fontMetrics = QFontMetrics(opt.font);
+ }
+
+ // set text alignment
+ value = index.data(Qt::TextAlignmentRole);
+ if (value.isValid())
+ opt.displayAlignment = (Qt::Alignment)value.toInt();
+
+ // set foreground brush
+ value = index.data(Qt::ForegroundRole);
+ if (qVariantCanConvert<QBrush>(value))
+ opt.palette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value));
+
+ return opt;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qitemdelegate.cpp"
+
+#endif // QT_NO_ITEMVIEWS