summaryrefslogtreecommitdiffstats
path: root/src/widgets/itemviews/qitemdelegate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/itemviews/qitemdelegate.cpp')
-rw-r--r--src/widgets/itemviews/qitemdelegate.cpp182
1 files changed, 73 insertions, 109 deletions
diff --git a/src/widgets/itemviews/qitemdelegate.cpp b/src/widgets/itemviews/qitemdelegate.cpp
index dff4cc4593..d1c7bb3d58 100644
--- a/src/widgets/itemviews/qitemdelegate.cpp
+++ b/src/widgets/itemviews/qitemdelegate.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qitemdelegate.h"
@@ -58,6 +22,7 @@
#include <qmetaobject.h>
#include <qtextlayout.h>
#include <private/qabstractitemdelegate_p.h>
+#include <private/qabstractitemmodel_p.h>
#include <private/qtextengine_p.h>
#include <qdebug.h>
#include <qlocale.h>
@@ -77,7 +42,7 @@ class QItemDelegatePrivate : public QAbstractItemDelegatePrivate
Q_DECLARE_PUBLIC(QItemDelegate)
public:
- QItemDelegatePrivate() : f(0), clipPainting(true) {}
+ QItemDelegatePrivate() : f(nullptr), clipPainting(true) {}
inline const QItemEditorFactory *editorFactory() const
{ return f ? f : QItemEditorFactory::defaultFactory(); }
@@ -94,7 +59,7 @@ public:
inline static QString replaceNewLine(QString text)
{
- text.replace(QLatin1Char('\n'), QChar::LineSeparator);
+ text.replace(u'\n', QChar::LineSeparator);
return text;
}
@@ -149,7 +114,7 @@ QRect QItemDelegatePrivate::textLayoutBounds(const QStyleOptionViewItem &option,
QStyle *style = w ? w->style() : QApplication::style();
const bool wrapText = option.features & QStyleOptionViewItem::WrapText;
// see QItemDelegate::drawDisplay
- const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, w) + 1;
+ const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, nullptr, w) + 1;
switch (option.decorationPosition) {
case QStyleOptionViewItem::Left:
case QStyleOptionViewItem::Right:
@@ -266,8 +231,7 @@ QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const
\row \li \l Qt::AccessibleDescriptionRole \li QString
\row \li \l Qt::AccessibleTextRole \li QString
\endomit
- \row \li \l Qt::BackgroundRole \li QBrush
- \row \li \l Qt::BackgroundColorRole \li QColor (obsolete; use Qt::BackgroundRole instead)
+ \row \li \l Qt::BackgroundRole \li QBrush (\since 4.2)
\row \li \l Qt::CheckStateRole \li Qt::CheckState
\row \li \l Qt::DecorationRole \li QIcon, QPixmap and QColor
\row \li \l Qt::DisplayRole \li QString and types with a string representation
@@ -278,8 +242,7 @@ QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const
\row \li \l Qt::StatusTipRole \li
\endomit
\row \li \l Qt::TextAlignmentRole \li Qt::Alignment
- \row \li \l Qt::ForegroundRole \li QBrush
- \row \li \l Qt::TextColorRole \li QColor (obsolete; use Qt::ForegroundRole instead)
+ \row \li \l Qt::ForegroundRole \li QBrush (\since 4.2)
\omit
\row \li \l Qt::ToolTipRole
\row \li \l Qt::WhatsThisRole
@@ -294,17 +257,27 @@ QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const
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,
+ render items suitably for all the required states; such as 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}.
+ You can provide custom editors by using a QItemEditorFactory. The following
+ code shows how a custom editor can be made available to delegates with the
+ default item editor factory.
+
+ \snippet code/src_gui_itemviews_qitemeditorfactory.cpp setDefaultFactory
+
+ After the default factory has been set, all standard item delegates
+ will use it (also the delegates that were created before setting the
+ default factory).
+
+ This way, you can avoid subclassing QItemDelegate, and all values of the
+ specified type (for example QMetaType::QDateTime) will be edited using the
+ provided editor (like \c{MyFancyDateTimeEdit} in the above example).
+
+ An alternative is to reimplement createEditor(), setEditorData(),
+ setModelData(), and updateEditorGeometry(). This process is described
+ in the \l{A simple delegate}{Model/View Programming overview documentation}.
\section1 QStyledItemDelegate vs. QItemDelegate
@@ -318,9 +291,7 @@ QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const
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}
+ \sa {Delegate Classes}, QStyledItemDelegate, QAbstractItemDelegate
*/
/*!
@@ -380,8 +351,10 @@ QString QItemDelegatePrivate::valueToText(const QVariant &value, const QStyleOpt
For example, a selected item may need to be displayed differently to
unselected items, as shown in the following code:
- \snippet itemviews/pixelator/pixeldelegate.cpp 2
- \dots
+ \code
+ if (option.state & QStyle::State_Selected)
+ painter->fillRect(option.rect, option.palette.highlight());
+ \endcode
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,
@@ -414,7 +387,7 @@ void QItemDelegate::paint(QPainter *painter,
if (value.isValid()) {
// ### we need the pixmap to call the virtual function
pixmap = decoration(opt, value);
- if (value.type() == QVariant::Icon) {
+ if (value.userType() == QMetaType::QIcon) {
d->tmp.icon = qvariant_cast<QIcon>(value);
d->tmp.mode = d->iconMode(option.state);
d->tmp.state = d->iconState(option.state);
@@ -434,7 +407,7 @@ void QItemDelegate::paint(QPainter *painter,
Qt::CheckState checkState = Qt::Unchecked;
value = index.data(Qt::CheckStateRole);
if (value.isValid()) {
- checkState = static_cast<Qt::CheckState>(value.toInt());
+ checkState = QtPrivate::legacyEnumValueFromModelData<Qt::CheckState>(value);
checkRect = doCheck(opt, opt.rect, value);
}
@@ -502,9 +475,9 @@ QWidget *QItemDelegate::createEditor(QWidget *parent,
{
Q_D(const QItemDelegate);
if (!index.isValid())
- return 0;
+ return nullptr;
const QItemEditorFactory *factory = d->f;
- if (factory == 0)
+ if (factory == nullptr)
factory = QItemEditorFactory::defaultFactory();
QWidget *w = factory->createEditor(index.data(Qt::EditRole).userType(), parent);
if (w)
@@ -524,19 +497,14 @@ QWidget *QItemDelegate::createEditor(QWidget *parent,
void QItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
-#ifdef QT_NO_PROPERTIES
- Q_UNUSED(editor);
- Q_UNUSED(index);
-#else
QVariant v = index.data(Qt::EditRole);
QByteArray n = editor->metaObject()->userProperty().name();
if (!n.isEmpty()) {
if (!v.isValid())
- v = QVariant(editor->property(n).userType(), (const void *)0);
+ v = QVariant(editor->property(n).metaType());
editor->setProperty(n, v);
}
-#endif
}
/*!
@@ -554,11 +522,6 @@ 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);
@@ -568,7 +531,6 @@ void QItemDelegate::setModelData(QWidget *editor,
model->data(index, Qt::EditRole).userType());
if (!n.isEmpty())
model->setData(index, editor->property(n), Qt::EditRole);
-#endif
}
/*!
@@ -586,7 +548,7 @@ void QItemDelegate::updateEditorGeometry(QWidget *editor,
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 textRect = textRectangle(nullptr, option.rect, option.font, text);
QRect checkRect = doCheck(option, textRect, index.data(Qt::CheckStateRole));
QStyleOptionViewItem opt = option;
opt.showDecorationSelected = true; // let the editor take up all available space
@@ -654,7 +616,7 @@ void QItemDelegate::drawDisplay(QPainter *painter, const QStyleOptionViewItem &o
const QWidget *widget = d->widget(option);
QStyle *style = widget ? widget->style() : QApplication::style();
- const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, widget) + 1;
+ const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, nullptr, widget) + 1;
QRect textRect = rect.adjusted(textMargin, 0, -textMargin, 0); // remove width padding
const bool wrapText = opt.features & QStyleOptionViewItem::WrapText;
d->textOption.setWrapMode(wrapText ? QTextOption::WordWrap : QTextOption::ManualWrap);
@@ -697,10 +659,12 @@ void QItemDelegate::drawDisplay(QPainter *painter, const QStyleOptionViewItem &o
|| textRect.height() < textLayoutSize.height())) {
painter->save();
painter->setClipRect(layoutRect);
- d->textLayout.draw(painter, layoutRect.topLeft(), QVector<QTextLayout::FormatRange>(), layoutRect);
+ d->textLayout.draw(painter, layoutRect.topLeft(), QList<QTextLayout::FormatRange>(),
+ layoutRect);
painter->restore();
} else {
- d->textLayout.draw(painter, layoutRect.topLeft(), QVector<QTextLayout::FormatRange>(), layoutRect);
+ d->textLayout.draw(painter, layoutRect.topLeft(), QList<QTextLayout::FormatRange>(),
+ layoutRect);
}
}
@@ -724,8 +688,8 @@ void QItemDelegate::drawDecoration(QPainter *painter, const QStyleOptionViewItem
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);
+ const QPixmap pm = selectedPixmap(pixmap, option.palette, option.state & QStyle::State_Enabled);
+ painter->drawPixmap(p, pm);
} else {
painter->drawPixmap(p, pixmap);
}
@@ -789,7 +753,7 @@ void QItemDelegate::drawCheck(QPainter *painter,
const QWidget *widget = d->widget(option);
QStyle *style = widget ? widget->style() : QApplication::style();
- style->drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &opt, painter, widget);
+ style->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &opt, painter, widget);
}
/*!
@@ -841,7 +805,7 @@ void QItemDelegate::doLayout(const QStyleOptionViewItem &option,
const bool hasText = textRect->isValid();
const bool hasMargin = (hasText | hasPixmap | hasCheck);
const int frameHMargin = hasMargin ?
- style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, widget) + 1 : 0;
+ style->pixelMetric(QStyle::PM_FocusFrameHMargin, nullptr, widget) + 1 : 0;
const int textMargin = hasText ? frameHMargin : 0;
const int pixmapMargin = hasPixmap ? frameHMargin : 0;
const int checkMargin = hasCheck ? frameHMargin : 0;
@@ -969,12 +933,12 @@ void QItemDelegate::doLayout(const QStyleOptionViewItem &option,
QPixmap QItemDelegate::decoration(const QStyleOptionViewItem &option, const QVariant &variant) const
{
Q_D(const QItemDelegate);
- switch (variant.type()) {
- case QVariant::Icon: {
+ switch (variant.userType()) {
+ case QMetaType::QIcon: {
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: {
+ case QMetaType::QColor: {
static QPixmap pixmap(option.decorationSize);
pixmap.fill(qvariant_cast<QColor>(variant));
return pixmap; }
@@ -1001,35 +965,35 @@ static QString qPixmapSerial(quint64 i, bool enabled)
return QString((const QChar *)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
+QPixmap QItemDelegate::selectedPixmap(const QPixmap &pixmap, const QPalette &palette, bool enabled)
{
- QString key = qPixmapSerial(pixmap.cacheKey(), enabled);
- QPixmap *pm = QPixmapCache::find(key);
- if (!pm) {
+ const QString key = qPixmapSerial(pixmap.cacheKey(), enabled);
+ QPixmap pm;
+ if (!QPixmapCache::find(key, &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);
+ color.setAlphaF(0.3f);
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.sizeInBytes() >> 10) + 1;
+ pm = QPixmap(QPixmap::fromImage(img));
+ const int n = (img.sizeInBytes() >> 10) + 1;
if (QPixmapCache::cacheLimit() < n)
QPixmapCache::setCacheLimit(n);
- QPixmapCache::insert(key, selected);
- pm = QPixmapCache::find(key);
+ QPixmapCache::insert(key, pm);
}
return pm;
}
@@ -1046,24 +1010,24 @@ QRect QItemDelegate::rect(const QStyleOptionViewItem &option,
if (role == Qt::CheckStateRole)
return doCheck(option, option.rect, value);
if (value.isValid() && !value.isNull()) {
- switch (value.type()) {
- case QVariant::Invalid:
+ switch (value.userType()) {
+ case QMetaType::UnknownType:
break;
- case QVariant::Pixmap: {
+ case QMetaType::QPixmap: {
const QPixmap &pixmap = qvariant_cast<QPixmap>(value);
- return QRect(QPoint(0, 0), pixmap.size() / pixmap.devicePixelRatio() ); }
- case QVariant::Image: {
+ return QRect(QPoint(0, 0), pixmap.deviceIndependentSize().toSize()); }
+ case QMetaType::QImage: {
const QImage &image = qvariant_cast<QImage>(value);
- return QRect(QPoint(0, 0), image.size() / image.devicePixelRatio() ); }
- case QVariant::Icon: {
+ return QRect(QPoint(0, 0), image.deviceIndependentSize().toSize()); }
+ case QMetaType::QIcon: {
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:
+ case QMetaType::QColor:
return QRect(QPoint(0, 0), option.decorationSize);
- case QVariant::String:
+ case QMetaType::QString:
default: {
const QString text = d->valueToText(value, option);
value = index.data(Qt::FontRole);
@@ -1089,7 +1053,7 @@ QRect QItemDelegate::doCheck(const QStyleOptionViewItem &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 style->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &opt, widget);
}
return QRect();
}
@@ -1108,7 +1072,7 @@ QRect QItemDelegate::textRectangle(QPainter * /*painter*/, const QRect &rect,
QSizeF fpSize = d->doTextLayout(rect.width());
const QSize size = QSize(qCeil(fpSize.width()), qCeil(fpSize.height()));
// ###: textRectangle should take style option as argument
- const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
+ const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin, nullptr) + 1;
return QRect(0, 0, size.width() + 2 * textMargin, size.height());
}
@@ -1177,7 +1141,7 @@ bool QItemDelegate::editorEvent(QEvent *event,
QRect emptyRect;
doLayout(option, &checkRect, &emptyRect, &emptyRect, false);
QMouseEvent *me = static_cast<QMouseEvent*>(event);
- if (me->button() != Qt::LeftButton || !checkRect.contains(me->pos()))
+ if (me->button() != Qt::LeftButton || !checkRect.contains(me->position().toPoint()))
return false;
// eat the double click events inside the check rect
@@ -1193,7 +1157,7 @@ bool QItemDelegate::editorEvent(QEvent *event,
return false;
}
- Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
+ Qt::CheckState state = QtPrivate::legacyEnumValueFromModelData<Qt::CheckState>(value);
if (flags & Qt::ItemIsUserTristate)
state = ((Qt::CheckState)((state + 1) % 3));
else
@@ -1220,7 +1184,7 @@ QStyleOptionViewItem QItemDelegate::setOptions(const QModelIndex &index,
// set text alignment
value = index.data(Qt::TextAlignmentRole);
if (value.isValid())
- opt.displayAlignment = Qt::Alignment(value.toInt());
+ opt.displayAlignment = QtPrivate::legacyFlagValueFromModelData<Qt::Alignment>(value);
// set foreground brush
value = index.data(Qt::ForegroundRole);
@@ -1228,7 +1192,7 @@ QStyleOptionViewItem QItemDelegate::setOptions(const QModelIndex &index,
opt.palette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value));
// disable style animations for checkboxes etc. within itemviews (QTBUG-30146)
- opt.styleObject = 0;
+ opt.styleObject = nullptr;
return opt;
}