Commit 1f6887ef authored by Peter Penz's avatar Peter Penz
Browse files

Fix focus-rectangle issues

Assure that the focus-rectangle exactly matches to the bottom of
the rendered text.

BUG: 297203
BUG: 289804
FIXED-IN: 4.9.0
parent 270e0c3e
......@@ -179,6 +179,24 @@ QRectF KFileItemListWidget::textRect() const
return m_textRect;
}
QRectF KFileItemListWidget::textFocusRect() const
{
const_cast<KFileItemListWidget*>(this)->triggerCacheRefreshing();
if (m_layout == CompactLayout) {
// In the compact layout a larger textRect() is returned to be aligned
// with the iconRect(). This is useful to have a larger selection/hover-area
// when having a quite large icon size but only one line of text. Still the
// focus rectangle should be shown as narrow as possible around the text.
QRectF rect = m_textRect;
const TextInfo* topText = m_textInfo.value(m_sortedVisibleRoles.first());
const TextInfo* bottomText = m_textInfo.value(m_sortedVisibleRoles.last());
rect.setTop(topText->pos.y());
rect.setBottom(bottomText->pos.y() + bottomText->staticText.size().height());
return rect;
}
return m_textRect;
}
QRectF KFileItemListWidget::expansionToggleRect() const
{
const_cast<KFileItemListWidget*>(this)->triggerCacheRefreshing();
......@@ -233,27 +251,26 @@ QSizeF KFileItemListWidget::itemSizeHint(int index, const KItemListView* view)
const QString text = KStringHandler::preProcessWrap(values["name"].toString());
const qreal maxWidth = view->itemSize().width() - 2 * option.padding;
int textLinesCount = 0;
QTextLine line;
// Calculate the number of lines required for wrapping the name
QTextOption textOption(Qt::AlignHCenter);
textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
qreal textHeight = 0;
QTextLayout layout(text, option.font);
layout.setTextOption(textOption);
layout.beginLayout();
while ((line = layout.createLine()).isValid()) {
line.setLineWidth(maxWidth);
line.naturalTextWidth();
++textLinesCount;
textHeight += line.height();
}
layout.endLayout();
// Add one line for each additional information
textLinesCount += additionalRolesCount;
const qreal height = textLinesCount * option.fontMetrics.height() +
const qreal height = textHeight +
additionalRolesCount * option.fontMetrics.lineSpacing() +
option.iconSize +
option.padding * 3;
return QSizeF(view->itemSize().width(), height);
......@@ -271,7 +288,7 @@ QSizeF KFileItemListWidget::itemSizeHint(int index, const KItemListView* view)
}
const qreal width = option.padding * 4 + option.iconSize + maximumRequiredWidth;
const qreal height = option.padding * 2 + qMax(option.iconSize, (1 + additionalRolesCount) * option.fontMetrics.height());
const qreal height = option.padding * 2 + qMax(option.iconSize, (1 + additionalRolesCount) * option.fontMetrics.lineSpacing());
return QSizeF(width, height);
}
......@@ -679,7 +696,7 @@ void KFileItemListWidget::updateIconsLayoutTextCache()
const qreal padding = option.padding;
const qreal maxWidth = size().width() - 2 * padding;
const qreal widgetHeight = size().height();
const qreal fontHeight = option.fontMetrics.height();
const qreal lineSpacing = option.fontMetrics.lineSpacing();
// Initialize properties for the "name" role. It will be used as anchor
// for initializing the position of the other roles.
......@@ -687,8 +704,8 @@ void KFileItemListWidget::updateIconsLayoutTextCache()
nameTextInfo->staticText.setText(KStringHandler::preProcessWrap(values["name"].toString()));
// Calculate the number of lines required for the name and the required width
int textLinesCountForName = 0;
qreal requiredWidthForName = 0;
qreal nameWidth = 0;
qreal nameHeight = 0;
QTextLine line;
QTextLayout layout(nameTextInfo->staticText.text(), option.font);
......@@ -696,25 +713,25 @@ void KFileItemListWidget::updateIconsLayoutTextCache()
layout.beginLayout();
while ((line = layout.createLine()).isValid()) {
line.setLineWidth(maxWidth);
requiredWidthForName = qMax(requiredWidthForName, line.naturalTextWidth());
++textLinesCountForName;
nameWidth = qMax(nameWidth, line.naturalTextWidth());
nameHeight += line.height();
}
layout.endLayout();
// Use one line for each additional information
int textLinesCount = textLinesCountForName;
const int additionalRolesCount = qMax(visibleRoles().count() - 1, 0);
textLinesCount += additionalRolesCount;
nameTextInfo->staticText.setTextWidth(maxWidth);
nameTextInfo->pos = QPointF(padding, widgetHeight - textLinesCount * fontHeight - padding);
m_textRect = QRectF(padding + (maxWidth - requiredWidthForName) / 2,
nameTextInfo->pos = QPointF(padding, widgetHeight -
nameHeight -
additionalRolesCount * lineSpacing -
padding);
m_textRect = QRectF(padding + (maxWidth - nameWidth) / 2,
nameTextInfo->pos.y(),
requiredWidthForName,
textLinesCountForName * fontHeight);
nameWidth,
nameHeight);
// Calculate the position for each additional information
qreal y = nameTextInfo->pos.y() + textLinesCountForName * fontHeight;
qreal y = nameTextInfo->pos.y() + nameHeight;
foreach (const QByteArray& role, m_sortedVisibleRoles) {
if (role == "name") {
continue;
......@@ -747,10 +764,10 @@ void KFileItemListWidget::updateIconsLayoutTextCache()
textInfo->pos = QPointF(padding, y);
textInfo->staticText.setTextWidth(maxWidth);
const QRectF textRect(padding + (maxWidth - requiredWidth) / 2, y, requiredWidth, fontHeight);
const QRectF textRect(padding + (maxWidth - requiredWidth) / 2, y, requiredWidth, lineSpacing);
m_textRect |= textRect;
y += fontHeight;
y += lineSpacing;
}
// Add a padding to the text rectangle
......@@ -767,13 +784,13 @@ void KFileItemListWidget::updateCompactLayoutTextCache()
const KItemListStyleOption& option = styleOption();
const qreal widgetHeight = size().height();
const qreal fontHeight = option.fontMetrics.height();
const qreal textLinesHeight = qMax(visibleRoles().count(), 1) * fontHeight;
const qreal lineSpacing = option.fontMetrics.lineSpacing();
const qreal textLinesHeight = qMax(visibleRoles().count(), 1) * lineSpacing;
const int scaledIconSize = (textLinesHeight < option.iconSize) ? widgetHeight - 2 * option.padding : option.iconSize;
qreal maximumRequiredTextWidth = 0;
const qreal x = option.padding * 3 + scaledIconSize;
qreal y = (widgetHeight - textLinesHeight) / 2;
qreal y = qRound((widgetHeight - textLinesHeight) / 2);
const qreal maxWidth = size().width() - x - option.padding;
foreach (const QByteArray& role, m_sortedVisibleRoles) {
const QString text = roleText(role, values);
......@@ -792,7 +809,7 @@ void KFileItemListWidget::updateCompactLayoutTextCache()
maximumRequiredTextWidth = qMax(maximumRequiredTextWidth, requiredWidth);
y += fontHeight;
y += lineSpacing;
}
m_textRect = QRectF(x - option.padding, 0, maximumRequiredTextWidth + 2 * option.padding, widgetHeight);
......
......@@ -56,6 +56,7 @@ public:
virtual QRectF iconRect() const;
virtual QRectF textRect() const;
virtual QRectF textFocusRect() const;
virtual QRectF expansionToggleRect() const;
virtual QRectF selectionToggleRect() const;
......
......@@ -122,17 +122,7 @@ void KItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsItem* o
if (isCurrent()) {
QStyleOptionFocusRect focusRectOption;
focusRectOption.initFrom(widget);
const QRect iconBounds = iconRect().toRect();
const QRect textBounds = textRect().toRect();
if (iconBounds.bottom() > textBounds.top()) {
focusRectOption.rect = textBounds;
} else {
// See KItemListWidget::drawItemStyleOption(): The selection rectangle
// gets decreased.
focusRectOption.rect = textBounds.adjusted(1, 1, -1, -1);
}
focusRectOption.rect = textFocusRect().toRect();
focusRectOption.state = QStyle::State_Enabled | QStyle::State_Item | QStyle::State_KeyboardFocusChange;
if (m_selected) {
focusRectOption.state |= QStyle::State_Selected;
......@@ -330,6 +320,11 @@ bool KItemListWidget::contains(const QPointF& point) const
selectionToggleRect().contains(point);
}
QRectF KItemListWidget::textFocusRect() const
{
return textRect();
}
QRectF KItemListWidget::selectionToggleRect() const
{
return QRectF();
......@@ -460,7 +455,7 @@ void KItemListWidget::drawItemStyleOption(QPainter* painter, QWidget* widget, QS
viewItemOption.state = styleState;
viewItemOption.viewItemPosition = QStyleOptionViewItemV4::OnlyOne;
viewItemOption.showDecorationSelected = true;
viewItemOption.rect = textBounds.adjusted(1, 0, -1, 0);
viewItemOption.rect = textBounds;
widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &viewItemOption, painter, widget);
}
......
......@@ -120,6 +120,15 @@ public:
*/
virtual QRectF textRect() const = 0;
/**
* @return Focus rectangle for indicating the current item. Per default
* textRect() will be returned. Overwrite this method if textRect()
* provides a larger rectangle than the actual text (e.g. to
* be aligned with the iconRect()). The textFocusRect() may not be
* outside the boundaries of textRect().
*/
virtual QRectF textFocusRect() const;
/**
* @return Rectangle for the selection-toggle that is used to select or deselect an item.
* Per default an empty rectangle is returned which means that no selection-toggle
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment