X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/92a4b5bb625fb10ebc4b15ea6483fb19a73fe60b..6cec386192e58089b4572996a265c9696cdcb3c0:/src/kitemviews/kstandarditemlistwidget.cpp diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp index 8d943ae16..e58340fb8 100644 --- a/src/kitemviews/kstandarditemlistwidget.cpp +++ b/src/kitemviews/kstandarditemlistwidget.cpp @@ -1,21 +1,8 @@ -/*************************************************************************** - * Copyright (C) 2012 by Peter Penz * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - ***************************************************************************/ +/* + * SPDX-FileCopyrightText: 2012 Peter Penz + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ #include "kstandarditemlistwidget.h" @@ -88,7 +75,7 @@ qreal KStandardItemListWidgetInformant::preferredRoleColumnWidth(const QByteArra // If current item is a link, we use the customized link font metrics instead of the normal font metrics. const QFontMetrics& fontMetrics = itemIsLink(index, view) ? linkFontMetrics : normalFontMetrics; - width += fontMetrics.width(text); + width += fontMetrics.horizontalAdvance(text); if (role == "text") { if (view->supportsItemExpanding()) { @@ -113,8 +100,8 @@ QString KStandardItemListWidgetInformant::itemText(int index, const KItemListVie bool KStandardItemListWidgetInformant::itemIsLink(int index, const KItemListView* view) const { - Q_UNUSED(index); - Q_UNUSED(view); + Q_UNUSED(index) + Q_UNUSED(view) return false; } @@ -214,12 +201,12 @@ void KStandardItemListWidgetInformant::calculateCompactLayoutItemSizeHints(QVect qreal maximumRequiredWidth = 0.0; if (showOnlyTextRole) { - maximumRequiredWidth = fontMetrics.width(itemText(index, view)); + maximumRequiredWidth = fontMetrics.horizontalAdvance(itemText(index, view)); } else { const QHash& values = view->model()->data(index); - foreach (const QByteArray& role, visibleRoles) { + for (const QByteArray& role : visibleRoles) { const QString& text = roleText(role, values); - const qreal requiredWidth = fontMetrics.width(text); + const qreal requiredWidth = fontMetrics.horizontalAdvance(text); maximumRequiredWidth = qMax(maximumRequiredWidth, requiredWidth); } } @@ -245,6 +232,7 @@ void KStandardItemListWidgetInformant::calculateDetailsLayoutItemSizeHints(QVect KStandardItemListWidget::KStandardItemListWidget(KItemListWidgetInformant* informant, QGraphicsItem* parent) : KItemListWidget(informant, parent), + m_textInfo(), m_isCut(false), m_isHidden(false), m_customizedFont(), @@ -260,7 +248,6 @@ KStandardItemListWidget::KStandardItemListWidget(KItemListWidgetInformant* infor m_scaledPixmapSize(), m_iconRect(), m_hoverPixmap(), - m_textInfo(), m_textRect(), m_sortedVisibleRoles(), m_expansionArea(), @@ -327,7 +314,7 @@ void KStandardItemListWidget::paint(QPainter* painter, const QStyleOptionGraphic } const KItemListStyleOption& itemListStyleOption = styleOption(); - if (isHovered()) { + if (isHovered() && !m_pixmap.isNull()) { if (hoverOpacity() < 1.0) { /* * Linear interpolation between m_pixmap and m_hoverPixmap. @@ -370,7 +357,7 @@ void KStandardItemListWidget::paint(QPainter* painter, const QStyleOptionGraphic } else { drawPixmap(painter, m_hoverPixmap); } - } else { + } else if (!m_pixmap.isNull()) { drawPixmap(painter, m_pixmap); } @@ -478,7 +465,7 @@ QRectF KStandardItemListWidget::textFocusRect() const const KItemListStyleOption& option = styleOption(); if (option.extendedSelectionRegion) { const QString text = textInfo->staticText.text(); - rect.setWidth(m_customizedFontMetrics.width(text) + 2 * option.padding); + rect.setWidth(m_customizedFontMetrics.horizontalAdvance(text) + 2 * option.padding); } return rect; @@ -600,7 +587,7 @@ void KStandardItemListWidget::refreshCache() bool KStandardItemListWidget::isRoleRightAligned(const QByteArray& role) const { - Q_UNUSED(role); + Q_UNUSED(role) return false; } @@ -665,13 +652,14 @@ QString KStandardItemListWidget::roleText(const QByteArray& role, void KStandardItemListWidget::dataChanged(const QHash& current, const QSet& roles) { - Q_UNUSED(current); + Q_UNUSED(current) m_dirtyContent = true; QSet dirtyRoles; if (roles.isEmpty()) { - dirtyRoles = visibleRoles().toSet(); + const auto visibleRoles = this->visibleRoles(); + dirtyRoles = QSet(visibleRoles.constBegin(), visibleRoles.constEnd()); } else { dirtyRoles = roles; } @@ -697,7 +685,7 @@ void KStandardItemListWidget::dataChanged(const QHash& cur void KStandardItemListWidget::visibleRolesChanged(const QList& current, const QList& previous) { - Q_UNUSED(previous); + Q_UNUSED(previous) m_sortedVisibleRoles = current; m_dirtyLayout = true; } @@ -706,38 +694,38 @@ void KStandardItemListWidget::columnWidthChanged(const QByteArray& role, qreal current, qreal previous) { - Q_UNUSED(role); - Q_UNUSED(current); - Q_UNUSED(previous); + Q_UNUSED(role) + Q_UNUSED(current) + Q_UNUSED(previous) m_dirtyLayout = true; } void KStandardItemListWidget::styleOptionChanged(const KItemListStyleOption& current, const KItemListStyleOption& previous) { - Q_UNUSED(current); - Q_UNUSED(previous); + Q_UNUSED(current) + Q_UNUSED(previous) updateAdditionalInfoTextColor(); m_dirtyLayout = true; } void KStandardItemListWidget::hoveredChanged(bool hovered) { - Q_UNUSED(hovered); + Q_UNUSED(hovered) m_dirtyLayout = true; } void KStandardItemListWidget::selectedChanged(bool selected) { - Q_UNUSED(selected); + Q_UNUSED(selected) updateAdditionalInfoTextColor(); m_dirtyContent = true; } void KStandardItemListWidget::siblingsInformationChanged(const QBitArray& current, const QBitArray& previous) { - Q_UNUSED(current); - Q_UNUSED(previous); + Q_UNUSED(current) + Q_UNUSED(previous) m_dirtyLayout = true; } @@ -748,12 +736,12 @@ int KStandardItemListWidget::selectionLength(const QString& text) const void KStandardItemListWidget::editedRoleChanged(const QByteArray& current, const QByteArray& previous) { - Q_UNUSED(previous); + Q_UNUSED(previous) QGraphicsView* parent = scene()->views()[0]; if (current.isEmpty() || !parent || current != "text") { if (m_roleEditor) { - emit roleEditingCanceled(index(), current, data().value(current)); + Q_EMIT roleEditingCanceled(index(), current, data().value(current)); disconnect(m_roleEditor, &KItemListRoleEditor::roleEditingCanceled, this, &KStandardItemListWidget::slotRoleEditingCanceled); @@ -776,6 +764,7 @@ void KStandardItemListWidget::editedRoleChanged(const QByteArray& current, const m_roleEditor = new KItemListRoleEditor(parent); m_roleEditor->setRole(current); + m_roleEditor->setAllowUpDownKeyChainEdit(m_layout != IconsLayout); m_roleEditor->setFont(styleOption().font); const QString text = data().value(current).toString(); @@ -878,7 +867,7 @@ void KStandardItemListWidget::slotRoleEditingCanceled(const QByteArray& role, const QVariant& value) { closeRoleEditor(); - emit roleEditingCanceled(index(), role, value); + Q_EMIT roleEditingCanceled(index(), role, value); setEditedRole(QByteArray()); } @@ -886,7 +875,7 @@ void KStandardItemListWidget::slotRoleEditingFinished(const QByteArray& role, const QVariant& value) { closeRoleEditor(); - emit roleEditingFinished(index(), role, value); + Q_EMIT roleEditingFinished(index(), role, value); setEditedRole(QByteArray()); } @@ -974,6 +963,11 @@ void KStandardItemListWidget::updatePixmapCache() KPixmapModifier::scale(m_pixmap, QSize(maxIconWidth, maxIconHeight) * qApp->devicePixelRatio()); } + if (m_pixmap.isNull()) { + m_hoverPixmap = QPixmap(); + return; + } + if (m_isCut) { KIconEffect* effect = KIconLoader::global()->iconEffect(); m_pixmap = effect->apply(m_pixmap, KIconLoader::Desktop, KIconLoader::DisabledState); @@ -986,6 +980,10 @@ void KStandardItemListWidget::updatePixmapCache() if (m_layout == IconsLayout && isSelected()) { const QColor color = palette().brush(QPalette::Normal, QPalette::Highlight).color(); QImage image = m_pixmap.toImage(); + if (image.isNull()) { + m_hoverPixmap = QPixmap(); + return; + } KIconEffect::colorize(image, color, 0.8f); m_pixmap = QPixmap::fromImage(image); } @@ -1113,6 +1111,26 @@ void KStandardItemListWidget::updateTextsCache() } } +QString KStandardItemListWidget::elideRightKeepExtension(const QString &text, int elidingWidth) const +{ + const auto extensionIndex = text.lastIndexOf('.'); + if (extensionIndex != -1) { + // has file extension + const auto extensionLength = text.length() - extensionIndex; + const auto extensionWidth = m_customizedFontMetrics.horizontalAdvance(text.right(extensionLength)); + if (elidingWidth > extensionWidth && extensionLength < 6 && (float(extensionWidth) / float(elidingWidth)) < 0.3) { + // if we have room to display the file extension and the extension is not too long + QString ret = m_customizedFontMetrics.elidedText(text.chopped(extensionLength), + Qt::ElideRight, + elidingWidth - extensionWidth); + ret.append(text.rightRef(extensionLength)); + return ret; + } + } + return m_customizedFontMetrics.elidedText(text,Qt::ElideRight, + elidingWidth); +} + void KStandardItemListWidget::updateIconsLayoutTextCache() { // +------+ @@ -1164,13 +1182,11 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() qreal lastLineWidth; do { QString lastTextLine = nameText.mid(line.textStart()); - lastTextLine = m_customizedFontMetrics.elidedText(lastTextLine, - Qt::ElideRight, - elidingWidth); + lastTextLine = elideRightKeepExtension(lastTextLine, elidingWidth); const QString elidedText = nameText.left(line.textStart()) + lastTextLine; nameTextInfo->staticText.setText(elidedText); - lastLineWidth = m_customizedFontMetrics.boundingRect(lastTextLine).width(); + lastLineWidth = m_customizedFontMetrics.horizontalAdvance(lastTextLine); // We do the text eliding in a loop with decreasing width (1 px / iteration) // to avoid problems related to different width calculation code paths @@ -1199,7 +1215,7 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() // Calculate the position for each additional information qreal y = nameTextInfo->pos.y() + nameHeight; - foreach (const QByteArray& role, m_sortedVisibleRoles) { + for (const QByteArray& role : qAsConst(m_sortedVisibleRoles)) { if (role == "text") { continue; } @@ -1221,11 +1237,11 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() textLine.setLineWidth(maxWidth); requiredWidth = textLine.naturalTextWidth(); if (requiredWidth > maxWidth) { - const QString elidedText = m_customizedFontMetrics.elidedText(text, Qt::ElideRight, maxWidth); + const QString elidedText = elideRightKeepExtension(text, maxWidth); textInfo->staticText.setText(elidedText); - requiredWidth = m_customizedFontMetrics.width(elidedText); + requiredWidth = m_customizedFontMetrics.horizontalAdvance(elidedText); } else if (role == "rating") { - // Use the width of the rating pixmap, because the rating text is empty. + // Use the width of the rating pixmap, because the rating text is empty. requiredWidth = m_rating.width(); } } @@ -1262,15 +1278,15 @@ void KStandardItemListWidget::updateCompactLayoutTextCache() const qreal x = option.padding * 3 + scaledIconSize; qreal y = qRound((widgetHeight - textLinesHeight) / 2); const qreal maxWidth = size().width() - x - option.padding; - foreach (const QByteArray& role, m_sortedVisibleRoles) { + for (const QByteArray& role : qAsConst(m_sortedVisibleRoles)) { const QString text = roleText(role, values); TextInfo* textInfo = m_textInfo.value(role); textInfo->staticText.setText(text); - qreal requiredWidth = m_customizedFontMetrics.width(text); + qreal requiredWidth = m_customizedFontMetrics.horizontalAdvance(text); if (requiredWidth > maxWidth) { requiredWidth = maxWidth; - const QString elidedText = m_customizedFontMetrics.elidedText(text, Qt::ElideRight, maxWidth); + const QString elidedText = elideRightKeepExtension(text, maxWidth); textInfo->staticText.setText(elidedText); } @@ -1282,7 +1298,7 @@ void KStandardItemListWidget::updateCompactLayoutTextCache() y += lineSpacing; } - m_textRect = QRectF(x - 2 * option.padding, 0, maximumRequiredTextWidth + 3 * option.padding, widgetHeight); + m_textRect = QRectF(x - option.padding, 0, maximumRequiredTextWidth + 2 * option.padding, widgetHeight); } void KStandardItemListWidget::updateDetailsLayoutTextCache() @@ -1313,11 +1329,11 @@ void KStandardItemListWidget::updateDetailsLayoutTextCache() qreal x = firstColumnInc; const qreal y = qMax(qreal(option.padding), (widgetHeight - fontHeight) / 2); - foreach (const QByteArray& role, m_sortedVisibleRoles) { + for (const QByteArray& role : qAsConst(m_sortedVisibleRoles)) { QString text = roleText(role, values); // Elide the text in case it does not fit into the available column-width - qreal requiredWidth = m_customizedFontMetrics.width(text); + qreal requiredWidth = m_customizedFontMetrics.horizontalAdvance(text); const qreal roleWidth = columnWidth(role); qreal availableTextWidth = roleWidth - columnWidthInc; @@ -1327,8 +1343,8 @@ void KStandardItemListWidget::updateDetailsLayoutTextCache() } if (requiredWidth > availableTextWidth) { - text = m_customizedFontMetrics.elidedText(text, Qt::ElideRight, availableTextWidth); - requiredWidth = m_customizedFontMetrics.width(text); + text = elideRightKeepExtension(text, availableTextWidth); + requiredWidth = m_customizedFontMetrics.horizontalAdvance(text); } TextInfo* textInfo = m_textInfo.value(role); @@ -1340,8 +1356,8 @@ void KStandardItemListWidget::updateDetailsLayoutTextCache() const qreal textWidth = option.extendedSelectionRegion ? size().width() - textInfo->pos.x() : requiredWidth + 2 * option.padding; - m_textRect = QRectF(textInfo->pos.x() - 2 * option.padding, 0, - textWidth + option.padding, size().height()); + m_textRect = QRectF(textInfo->pos.x() - option.padding, 0, + textWidth, size().height()); // The column after the name should always be aligned on the same x-position independent // from the expansion-level shown in the name column @@ -1463,33 +1479,23 @@ QPixmap KStandardItemListWidget::pixmapForIcon(const QString& name, const QStrin { static const QIcon fallbackIcon = QIcon::fromTheme(QStringLiteral("unknown")); - int requestedSize = size; - if (size <= KIconLoader::SizeSmall) { - requestedSize = KIconLoader::SizeSmall; - } else if (size <= KIconLoader::SizeSmallMedium) { - requestedSize = KIconLoader::SizeSmallMedium; - } else if (size <= KIconLoader::SizeMedium) { - requestedSize = KIconLoader::SizeMedium; - } else if (size <= KIconLoader::SizeLarge) { - requestedSize = KIconLoader::SizeLarge; - } else if (size <= KIconLoader::SizeHuge) { - requestedSize = KIconLoader::SizeHuge; - } else if (size <= KIconLoader::SizeEnormous) { - requestedSize = KIconLoader::SizeEnormous; - } else if (size <= KIconLoader::SizeEnormous * 2) { - requestedSize = KIconLoader::SizeEnormous * 2; - } size *= qApp->devicePixelRatio(); - requestedSize *= qApp->devicePixelRatio(); - const QString key = "KStandardItemListWidget:" % name % ":" % overlays.join(QStringLiteral(":")) % ":" % QString::number(size) % ":" % QString::number(mode); + const QString key = "KStandardItemListWidget:" % name % ":" % overlays.join(QLatin1Char(':')) % ":" % QString::number(size) % ":" % QString::number(mode); QPixmap pixmap; - if (!QPixmapCache::find(key, pixmap)) { - const QIcon icon = QIcon::fromTheme(name, fallbackIcon); + if (!QPixmapCache::find(key, &pixmap)) { + QIcon icon = QIcon::fromTheme(name); + if (icon.isNull()) { + icon = QIcon(name); + } + if (icon.isNull() + || icon.pixmap(size / qApp->devicePixelRatio(), size / qApp->devicePixelRatio(), mode).isNull()) { + icon = fallbackIcon; + } - pixmap = icon.pixmap(requestedSize / qApp->devicePixelRatio(), requestedSize / qApp->devicePixelRatio(), mode); - if (requestedSize != size) { + pixmap = icon.pixmap(size / qApp->devicePixelRatio(), size / qApp->devicePixelRatio(), mode); + if (pixmap.width() != size || pixmap.height() != size) { KPixmapModifier::scale(pixmap, QSize(size, size)); } @@ -1498,11 +1504,27 @@ QPixmap KStandardItemListWidget::pixmapForIcon(const QString& name, const QStrin // It is more efficient to do it here, as KIconLoader::drawOverlays() // assumes that an overlay will be drawn and has some additional // setup time. - foreach (const QString& overlay, overlays) { + for (const QString& overlay : overlays) { if (!overlay.isEmpty()) { + int state = KIconLoader::DefaultState; + + switch (mode) { + case QIcon::Normal: + break; + case QIcon::Active: + state = KIconLoader::ActiveState; + break; + case QIcon::Disabled: + state = KIconLoader::DisabledState; + break; + case QIcon::Selected: + state = KIconLoader::SelectedState; + break; + } + // There is at least one overlay, draw all overlays above m_pixmap // and cancel the check - KIconLoader::global()->drawOverlays(overlays, pixmap, KIconLoader::Desktop); + KIconLoader::global()->drawOverlays(overlays, pixmap, KIconLoader::Desktop, state); break; } }