QListView: Prevent infinite loop when wrapping text of item with null-icon

If an item in a list view has a null icon, then the decorationSize gets
calculated as -1, -1. The style would then try to wrap the text to a
lineWidth of -1, ending up in an infinite loop in viewItemTextLayout.

To prevent that, don't set the HasDecoration flag of the style option
when the icon is null, and don't fall back ot the decorationSize unless
the flag is set.

Add a test for this particular item configuration. This also fixes the
widget baseline test with styles that don't provide all standard icons.

Pick-to: 6.5
Change-Id: I691db6abede9a9b2ad300f3ee7fbfdae5fb6097f
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
Reviewed-by: Santhosh Kumar <santhosh.kumar.selvaraj@qt.io>
This commit is contained in:
Volker Hilsheimer 2023-01-02 17:41:50 +01:00
parent 84a68ef75c
commit fb8701cb8b
3 changed files with 35 additions and 5 deletions

View File

@ -285,6 +285,10 @@ void QStyledItemDelegate::initStyleOption(QStyleOptionViewItem *option,
switch (value->userType()) {
case QMetaType::QIcon: {
option->icon = qvariant_cast<QIcon>(*value);
if (option->icon.isNull()) {
option->features &= ~QStyleOptionViewItem::HasDecoration;
break;
}
QIcon::Mode mode;
if (!(option->state & QStyle::State_Enabled))
mode = QIcon::Disabled;

View File

@ -941,12 +941,21 @@ QSize QCommonStylePrivate::viewItemSize(const QStyleOptionViewItem *option, int
break;
}
case QStyleOptionViewItem::Top:
case QStyleOptionViewItem::Bottom:
if (wrapText)
bounds.setWidth(bounds.isValid() ? bounds.width() - 2 * textMargin : option->decorationSize.width());
else
bounds.setWidth(QFIXED_MAX);
case QStyleOptionViewItem::Bottom: {
int width;
if (wrapText) {
if (bounds.isValid())
width = bounds.width() - 2 * textMargin;
else if (option->features & QStyleOptionViewItem::HasDecoration)
width = option->decorationSize.width();
else
width = 0;
} else {
width = QFIXED_MAX;
}
bounds.setWidth(width);
break;
}
default:
break;
}

View File

@ -156,6 +156,7 @@ private slots:
void spacingWithWordWrap();
void scrollOnRemove_data();
void scrollOnRemove();
void wordWrapNullIcon();
};
// Testing get/set functions
@ -3174,6 +3175,22 @@ void tst_QListView::scrollOnRemove()
QTRY_COMPARE(view.verticalScrollBar()->value(), item25Position);
}
void tst_QListView::wordWrapNullIcon()
{
QListView listView;
listView.setViewMode(QListView::IconMode);
listView.setWrapping(true);
listView.setWordWrap(true);
listView.setFixedSize(QSize(100, 500));
QStandardItemModel model;
QStandardItem *item = new QStandardItem(QIcon(), "This is a long text for word wrapping Item_");
model.appendRow(item);
listView.setModel(&model);
listView.indexAt(QPoint(0, 0));
}
QTEST_MAIN(tst_QListView)
#include "tst_qlistview.moc"