From: Kai Uwe Broulik Date: Fri, 25 Feb 2022 20:03:36 +0000 (+0100) Subject: Merge branch 'release/21.12' X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/commitdiff_plain/c68f1f6f8d6c24123c9c5df4d2e91a9d2462ceb6?hp=-c Merge branch 'release/21.12' --- c68f1f6f8d6c24123c9c5df4d2e91a9d2462ceb6 diff --combined src/kitemviews/kstandarditemlistwidget.cpp index 74d48e325,62beb6e53..e5c2f021b --- a/src/kitemviews/kstandarditemlistwidget.cpp +++ b/src/kitemviews/kstandarditemlistwidget.cpp @@@ -36,7 -36,7 +36,7 @@@ KStandardItemListWidgetInformant::~KSta { } -void KStandardItemListWidgetInformant::calculateItemSizeHints(QVector& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const +void KStandardItemListWidgetInformant::calculateItemSizeHints(QVector>& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const { switch (static_cast(view)->itemLayout()) { case KStandardItemListView::IconsLayout: @@@ -121,7 -121,7 +121,7 @@@ QFont KStandardItemListWidgetInformant: return baseFont; } -void KStandardItemListWidgetInformant::calculateIconsLayoutItemSizeHints(QVector& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const +void KStandardItemListWidgetInformant::calculateIconsLayoutItemSizeHints(QVector>& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const { const KItemListStyleOption& option = view->styleOption(); const QFont& normalFont = option.font; @@@ -138,7 -138,7 +138,7 @@@ textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); for (int index = 0; index < logicalHeightHints.count(); ++index) { - if (logicalHeightHints.at(index) > 0.0) { + if (logicalHeightHints.at(index).first > 0.0) { continue; } @@@ -146,7 -146,7 +146,7 @@@ const QFont& font = itemIsLink(index, view) ? linkFont : normalFont; const QString& text = KStringHandler::preProcessWrap(itemText(index, view)); - + // Calculate the number of lines required for wrapping the name qreal textHeight = 0; QTextLayout layout(text, font); @@@ -154,7 -154,6 +154,7 @@@ layout.beginLayout(); QTextLine line; int lineCount = 0; + bool isElided = false; while ((line = layout.createLine()).isValid()) { line.setLineWidth(maxWidth); line.naturalTextWidth(); @@@ -162,7 -161,6 +162,7 @@@ ++lineCount; if (lineCount == option.maxTextLines) { + isElided = layout.createLine().isValid(); break; } } @@@ -171,14 -169,13 +171,14 @@@ // Add one line for each additional information textHeight += additionalRolesSpacing; - logicalHeightHints[index] = textHeight + spacingAndIconHeight; + logicalHeightHints[index].first = textHeight + spacingAndIconHeight; + logicalHeightHints[index].second = isElided; } logicalWidthHint = itemWidth; } -void KStandardItemListWidgetInformant::calculateCompactLayoutItemSizeHints(QVector& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const +void KStandardItemListWidgetInformant::calculateCompactLayoutItemSizeHints(QVector>& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const { const KItemListStyleOption& option = view->styleOption(); const QFontMetrics& normalFontMetrics = option.fontMetrics; @@@ -193,7 -190,7 +193,7 @@@ const QFontMetrics linkFontMetrics(customizedFontForLinks(option.font)); for (int index = 0; index < logicalHeightHints.count(); ++index) { - if (logicalHeightHints.at(index) > 0.0) { + if (logicalHeightHints.at(index).first > 0.0) { continue; } @@@ -220,17 -217,17 +220,17 @@@ width = maxWidth; } - logicalHeightHints[index] = width; + logicalHeightHints[index].first = width; } logicalWidthHint = height; } -void KStandardItemListWidgetInformant::calculateDetailsLayoutItemSizeHints(QVector& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const +void KStandardItemListWidgetInformant::calculateDetailsLayoutItemSizeHints(QVector>& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const { const KItemListStyleOption& option = view->styleOption(); const qreal height = option.padding * 2 + qMax(option.iconSize, option.fontMetrics.height()); - logicalHeightHints.fill(height); + logicalHeightHints.fill(std::make_pair(height, false)); logicalWidthHint = -1.0; } @@@ -250,7 -247,6 +250,7 @@@ KStandardItemListWidget::KStandardItemL m_pixmapPos(), m_pixmap(), m_scaledPixmapSize(), + m_columnWidthSum(), m_iconRect(), m_hoverPixmap(), m_textRect(), @@@ -294,18 -290,6 +294,18 @@@ KStandardItemListWidget::Layout KStanda return m_layout; } +void KStandardItemListWidget::setHighlightEntireRow(bool highlightEntireRow) { + if (m_highlightEntireRow != highlightEntireRow) { + m_highlightEntireRow = highlightEntireRow; + m_dirtyLayout = true; + update(); + } +} + +bool KStandardItemListWidget::highlightEntireRow() const { + return m_highlightEntireRow; +} + void KStandardItemListWidget::setSupportsItemExpanding(bool supportsItemExpanding) { if (m_supportsItemExpanding != supportsItemExpanding) { @@@ -419,7 -403,7 +419,7 @@@ void KStandardItemListWidget::paint(QPa QPointF pos = ratingTextInfo->pos; const Qt::Alignment align = ratingTextInfo->staticText.textOption().alignment(); if (align & Qt::AlignHCenter) { - pos.rx() += (size().width() - m_rating.width()) / 2 - 2; + pos.rx() += (size().width() - m_rating.width() / m_rating.devicePixelRatioF()) / 2 - 2; } painter->drawPixmap(pos, m_rating); } @@@ -507,11 -491,7 +507,11 @@@ QRectF KStandardItemListWidget::selecti case DetailsLayout: { const int padding = styleOption().padding; QRectF adjustedIconRect = iconRect().adjusted(-padding, -padding, padding, padding); - return adjustedIconRect | m_textRect; + QRectF result = adjustedIconRect | m_textRect; + if (m_highlightEntireRow) { + result.setRight(m_columnWidthSum + leadingPadding()); + } + return result; } default: @@@ -532,11 -512,12 +532,11 @@@ QRectF KStandardItemListWidget::selecti { const_cast(this)->triggerCacheRefreshing(); - const int iconHeight = styleOption().iconSize; - + const int widgetIconSize = iconSize(); int toggleSize = KIconLoader::SizeSmall; - if (iconHeight >= KIconLoader::SizeEnormous) { + if (widgetIconSize >= KIconLoader::SizeEnormous) { toggleSize = KIconLoader::SizeMedium; - } else if (iconHeight >= KIconLoader::SizeLarge) { + } else if (widgetIconSize >= KIconLoader::SizeLarge) { toggleSize = KIconLoader::SizeSmallMedium; } @@@ -727,16 -708,11 +727,16 @@@ void KStandardItemListWidget::columnWid m_dirtyLayout = true; } +void KStandardItemListWidget::leadingPaddingChanged(qreal padding) { + Q_UNUSED(padding) + m_dirtyLayout = true; +} + void KStandardItemListWidget::styleOptionChanged(const KItemListStyleOption& current, const KItemListStyleOption& previous) { - Q_UNUSED(current) - Q_UNUSED(previous) + KItemListWidget::styleOptionChanged(current, previous); + updateAdditionalInfoTextColor(); m_dirtyLayout = true; } @@@ -832,15 -808,6 +832,15 @@@ void KStandardItemListWidget::editedRol m_roleEditor->setFocus(); } +void KStandardItemListWidget::iconSizeChanged(int current, int previous) +{ + KItemListWidget::iconSizeChanged(current, previous); + + invalidateIconCache(); + triggerCacheRefreshing(); + update(); +} + void KStandardItemListWidget::resizeEvent(QGraphicsSceneResizeEvent* event) { if (m_roleEditor) { @@@ -933,13 -900,10 +933,13 @@@ void KStandardItemListWidget::triggerCa m_isHidden = isHidden(); m_customizedFont = customizedFont(styleOption().font); m_customizedFontMetrics = QFontMetrics(m_customizedFont); + m_columnWidthSum = std::accumulate(m_sortedVisibleRoles.begin(), m_sortedVisibleRoles.end(), + qreal(), [this](qreal sum, const auto &role){ return sum + columnWidth(role); }); updateExpansionArea(); updateTextsCache(); updatePixmapCache(); + clearHoverCache(); m_dirtyLayout = false; m_dirtyContent = false; @@@ -952,16 -916,12 +952,16 @@@ void KStandardItemListWidget::updateExp const QHash values = data(); const int expandedParentsCount = values.value("expandedParentsCount", 0).toInt(); if (expandedParentsCount >= 0) { - const KItemListStyleOption& option = styleOption(); + const int widgetIconSize = iconSize(); const qreal widgetHeight = size().height(); - const qreal inc = (widgetHeight - option.iconSize) / 2; - const qreal x = expandedParentsCount * widgetHeight + inc; + const qreal inc = (widgetHeight - iconSize()) / 2; + const qreal x = + layoutDirection() == Qt::LeftToRight + ? expandedParentsCount * widgetHeight + inc + : size().width() - iconSize() - (expandedParentsCount * widgetHeight + inc); const qreal y = inc; - m_expansionArea = QRectF(x, y, option.iconSize, option.iconSize); + const qreal xPadding = m_highlightEntireRow ? leadingPadding() : 0; + m_expansionArea = QRectF(xPadding + x, y, widgetIconSize, widgetIconSize); return; } } @@@ -979,9 -939,8 +979,9 @@@ void KStandardItemListWidget::updatePix const KItemListStyleOption& option = styleOption(); const qreal padding = option.padding; - const int maxIconWidth = iconOnTop ? widgetSize.width() - 2 * padding : option.iconSize; - const int maxIconHeight = option.iconSize; + const int widgetIconSize = iconSize(); + const int maxIconWidth = iconOnTop ? widgetSize.width() - 2 * padding : widgetIconSize; + const int maxIconHeight = widgetIconSize; const QHash values = data(); @@@ -1095,20 -1054,8 +1095,20 @@@ } else { // Center horizontally and vertically within the icon-area const TextInfo* textInfo = m_textInfo.value("text"); - m_pixmapPos.setX(textInfo->pos.x() - 2.0 * padding - - (scaledIconSize + m_scaledPixmapSize.width()) / 2.0); + const auto width = (scaledIconSize + m_scaledPixmapSize.width()) / 2.0; + const auto iPadding = 2.0 * padding; + const auto x = textInfo->pos.x(); + + const QHash values = data(); + const int expandedParentsCount = values.value("expandedParentsCount", 0).toInt(); + const int expansionOffset = + (m_layout == DetailsLayout) ? + size().height() + size().height() * expandedParentsCount : + 0; + + m_pixmapPos.setX(layoutDirection() == Qt::LeftToRight + ? x - iPadding - width + expansionOffset + : size().width() - iPadding - width - expansionOffset); // Derive icon's vertical center from the center of the text frame, including // any necessary adjustment if the font's midline is offset from the frame center @@@ -1236,6 -1183,7 +1236,6 @@@ void KStandardItemListWidget::updateIco const KItemListStyleOption& option = styleOption(); const qreal padding = option.padding; const qreal maxWidth = size().width() - 2 * padding; - const qreal widgetHeight = size().height(); const qreal lineSpacing = m_customizedFontMetrics.lineSpacing(); // Initialize properties for the "text" role. It will be used as anchor @@@ -1289,8 -1237,12 +1289,8 @@@ layout.endLayout(); // Use one line for each additional information - const int additionalRolesCount = qMax(visibleRoles().count() - 1, 0); nameTextInfo->staticText.setTextWidth(maxWidth); - nameTextInfo->pos = QPointF(padding, widgetHeight - - nameHeight - - additionalRolesCount * lineSpacing - - padding); + nameTextInfo->pos = QPointF(padding, iconSize() + 2 * padding); m_textRect = QRectF(padding + (maxWidth - nameWidth) / 2, nameTextInfo->pos.y(), nameWidth, @@@ -1325,7 -1277,7 +1325,7 @@@ requiredWidth = m_customizedFontMetrics.horizontalAdvance(elidedText); } else if (role == "rating") { // Use the width of the rating pixmap, because the rating text is empty. - requiredWidth = m_rating.width(); + requiredWidth = m_rating.width() / m_rating.devicePixelRatioF(); } } layout.endLayout(); @@@ -1334,11 -1286,7 +1334,11 @@@ textInfo->staticText.setTextWidth(maxWidth); const QRectF textRect(padding + (maxWidth - requiredWidth) / 2, y, requiredWidth, lineSpacing); - m_textRect |= textRect; + + // Ignore empty roles. Avoids a text rect taller than the area that actually contains text. + if (!textRect.isEmpty()) { + m_textRect |= textRect; + } y += lineSpacing; } @@@ -1359,9 -1307,10 +1359,9 @@@ void KStandardItemListWidget::updateCom const qreal widgetHeight = size().height(); const qreal lineSpacing = m_customizedFontMetrics.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; + const qreal x = option.padding * 3 + iconSize(); qreal y = qRound((widgetHeight - textLinesHeight) / 2); const qreal maxWidth = size().width() - x - option.padding; for (const QByteArray& role : qAsConst(m_sortedVisibleRoles)) { @@@ -1376,11 -1325,7 +1376,11 @@@ textInfo->staticText.setText(elidedText); } - textInfo->pos = QPointF(x, y); + if (layoutDirection() == Qt::LeftToRight) { + textInfo->pos = QPointF(x, y); + } else { + textInfo->pos = QPointF(x - size().height(), y); + } textInfo->staticText.setTextWidth(maxWidth); maximumRequiredTextWidth = qMax(maximumRequiredTextWidth, requiredWidth); @@@ -1388,11 -1333,7 +1388,11 @@@ y += lineSpacing; } - m_textRect = QRectF(x - option.padding, 0, maximumRequiredTextWidth + 2 * option.padding, widgetHeight); + if (layoutDirection() == Qt::LeftToRight) { + m_textRect = QRectF(x - option.padding, 0, maximumRequiredTextWidth + 2 * option.padding, widgetHeight); + } else { + m_textRect = QRectF(x - option.padding - size().height(), 0, maximumRequiredTextWidth + 2 * option.padding, widgetHeight); + } } void KStandardItemListWidget::updateDetailsLayoutTextCache() @@@ -1409,18 -1350,18 +1409,18 @@@ const QHash values = data(); const qreal widgetHeight = size().height(); - const int scaledIconSize = widgetHeight - 2 * option.padding; const int fontHeight = m_customizedFontMetrics.height(); const qreal columnWidthInc = columnPadding(option); - qreal firstColumnInc = scaledIconSize; + + qreal firstColumnOffset = iconSize(); if (m_supportsItemExpanding) { - firstColumnInc += (m_expansionArea.left() + m_expansionArea.right() + widgetHeight) / 2; + firstColumnOffset += (m_expansionArea.width() + widgetHeight) / 2; } else { - firstColumnInc += option.padding; + firstColumnOffset += option.padding + leadingPadding(); } - qreal x = firstColumnInc; + qreal x = firstColumnOffset; const qreal y = qMax(qreal(option.padding), (widgetHeight - fontHeight) / 2); for (const QByteArray& role : qAsConst(m_sortedVisibleRoles)) { @@@ -1431,13 -1372,9 +1431,13 @@@ const qreal roleWidth = columnWidth(role); qreal availableTextWidth = roleWidth - columnWidthInc; + const QHash values = data(); + const int expandedParentsCount = values.value("expandedParentsCount", 0).toInt(); + const int expansionOffset = size().height() * expandedParentsCount; + const bool isTextRole = (role == "text"); if (isTextRole) { - availableTextWidth -= firstColumnInc; + availableTextWidth -= firstColumnOffset - leadingPadding(); } if (requiredWidth > availableTextWidth) { @@@ -1447,15 -1384,7 +1447,15 @@@ TextInfo* textInfo = m_textInfo.value(role); textInfo->staticText.setText(text); - textInfo->pos = QPointF(x + columnWidthInc / 2, y); + textInfo->pos = QPointF(x - (layoutDirection() == Qt::LeftToRight ? 0 : firstColumnOffset), y); + if (layoutDirection() == Qt::LeftToRight) { + textInfo->pos.rx() += columnWidthInc/2 + expansionOffset; + } else { + textInfo->pos.rx() -= expansionOffset; + if (textInfo->pos.x() < iconSize()) { + textInfo->pos.rx() = iconSize(); + } + } x += roleWidth; if (isTextRole) { @@@ -1467,7 -1396,7 +1467,7 @@@ // The column after the name should always be aligned on the same x-position independent // from the expansion-level shown in the name column - x -= firstColumnInc; + x -= firstColumnOffset - leadingPadding(); } else if (isRoleRightAligned(role)) { textInfo->pos.rx() += roleWidth - requiredWidth - columnWidthInc; } @@@ -1479,11 -1408,8 +1479,11 @@@ void KStandardItemListWidget::updateAdd QColor c1; if (m_customTextColor.isValid()) { c1 = m_customTextColor; - } else if (isSelected() && m_layout != DetailsLayout) { - c1 = styleOption().palette.highlightedText().color(); + } else if (isSelected()) { + // The detail text colour needs to match the main text (HighlightedText) for the same level + // of readability. We short circuit early here to avoid interpolating with another colour. + m_additionalInfoTextColor = styleOption().palette.color(QPalette::HighlightedText); + return; } else { c1 = styleOption().palette.text().color(); } @@@ -1519,27 -1445,18 +1519,27 @@@ void KStandardItemListWidget::drawPixma void KStandardItemListWidget::drawSiblingsInformation(QPainter* painter) { const int siblingSize = size().height(); - const int x = (m_expansionArea.left() + m_expansionArea.right() - siblingSize) / 2; - QRect siblingRect(x, 0, siblingSize, siblingSize); + const int x = (m_expansionArea.width() - siblingSize) / 2; + + const QHash values = data(); + const int expandedParentsCount = values.value("expandedParentsCount", 0).toInt(); + const int expansionOffset = siblingSize * expandedParentsCount; + + QRect siblingRect( + layoutDirection() == Qt::LeftToRight + ? x + expansionOffset + : size().width() - x - siblingSize - expansionOffset, 0, siblingSize, siblingSize); - QStyleOption option; - option.palette.setColor(QPalette::Text, option.palette.color(normalTextColorRole())); bool isItemSibling = true; const QBitArray siblings = siblingsInformation(); + QStyleOption option; + option.direction = layoutDirection(); + const auto normalColor = option.palette.color(normalTextColorRole()); + const auto highlightColor = option.palette.color(expansionAreaHovered() ? QPalette::Highlight : normalTextColorRole()); for (int i = siblings.count() - 1; i >= 0; --i) { option.rect = siblingRect; option.state = siblings.at(i) ? QStyle::State_Sibling : QStyle::State_None; - if (isItemSibling) { option.state |= QStyle::State_Item; if (m_isExpandable) { @@@ -1548,19 -1465,12 +1548,19 @@@ if (data().value("isExpanded").toBool()) { option.state |= QStyle::State_Open; } + option.palette.setColor(QPalette::Text, highlightColor); isItemSibling = false; + } else { + option.palette.setColor(QPalette::Text, normalColor); } style()->drawPrimitive(QStyle::PE_IndicatorBranch, &option, painter); - siblingRect.translate(-siblingRect.width(), 0); + if (layoutDirection() == Qt::LeftToRight) { + siblingRect.translate(-siblingRect.width(), 0); + } else { + siblingRect.translate(siblingRect.width(), 0); + } } }