]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kstandarditemlistwidget.cpp
Merge remote-tracking branch 'fork/work/zakharafoniam/useful-groups'
[dolphin.git] / src / kitemviews / kstandarditemlistwidget.cpp
index 729411c11b04817f39b9461d43c3858b2ed55068..2538cddcf6973fac086b3fed50fea7ef79b19f54 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "kstandarditemlistwidget.h"
 
+#include "dolphin_contentdisplaysettings.h"
 #include "kfileitemlistview.h"
 #include "private/kfileitemclipboard.h"
 #include "private/kitemlistroleeditor.h"
@@ -270,7 +271,6 @@ KStandardItemListWidget::KStandardItemListWidget(KItemListWidgetInformant *infor
     , m_scaledPixmapSize()
     , m_columnWidthSum()
     , m_iconRect()
-    , m_hoverPixmap()
     , m_textRect()
     , m_sortedVisibleRoles()
     , m_expansionArea()
@@ -345,7 +345,7 @@ void KStandardItemListWidget::paint(QPainter *painter, const QStyleOptionGraphic
         drawSiblingsInformation(painter);
     }
 
-    auto pixmap = isHovered() ? m_hoverPixmap : m_pixmap;
+    auto pixmap = m_pixmap;
     if (!m_overlays.isEmpty()) {
         const qreal dpr = KItemViewsUtils::devicePixelRatio(this);
 
@@ -387,7 +387,7 @@ void KStandardItemListWidget::paint(QPainter *painter, const QStyleOptionGraphic
             {
                 QPainter p(&pixmap2);
                 p.setOpacity(hoverOpacity());
-                p.drawPixmap(0, 0, m_hoverPixmap);
+                p.drawPixmap(0, 0, m_pixmap);
             }
 
             // Paint pixmap2 on pixmap1 using CompositionMode_Plus
@@ -483,12 +483,6 @@ void KStandardItemListWidget::paint(QPainter *painter, const QStyleOptionGraphic
 #endif
 }
 
-QRectF KStandardItemListWidget::iconRect() const
-{
-    const_cast<KStandardItemListWidget *>(this)->triggerCacheRefreshing();
-    return m_iconRect;
-}
-
 QRectF KStandardItemListWidget::textRect() const
 {
     const_cast<KStandardItemListWidget *>(this)->triggerCacheRefreshing();
@@ -536,35 +530,36 @@ QRectF KStandardItemListWidget::textFocusRect() const
     return m_textRect;
 }
 
-QRectF KStandardItemListWidget::selectionRect() const
+QRectF KStandardItemListWidget::selectionRectFull() const
 {
     const_cast<KStandardItemListWidget *>(this)->triggerCacheRefreshing();
-
-    switch (m_layout) {
-    case IconsLayout:
-        return m_textRect;
-
-    case CompactLayout:
-    case DetailsLayout: {
-        const int padding = styleOption().padding;
-        QRectF adjustedIconRect = iconRect().adjusted(-padding, -padding, padding, padding);
-        QRectF result = adjustedIconRect | m_textRect;
+    const int padding = styleOption().padding;
+    if (m_layout == DetailsLayout) {
+        auto rect = m_iconRect | m_textRect;
         if (m_highlightEntireRow) {
             if (layoutDirection() == Qt::LeftToRight) {
-                result.setRight(leftPadding() + m_columnWidthSum);
+                rect.setRight(leftPadding() + m_columnWidthSum);
             } else {
-                result.setLeft(size().width() - m_columnWidthSum - rightPadding());
+                rect.setLeft(size().width() - m_columnWidthSum - rightPadding());
             }
         }
-        return result;
+        return rect.adjusted(-padding, 0, padding, 0);
+    } else {
+        if (m_layout == CompactLayout) {
+            return rect().adjusted(-padding, 0, padding, 0);
+        }
+        return rect();
     }
+}
 
-    default:
-        Q_ASSERT(false);
-        break;
+QRectF KStandardItemListWidget::selectionRectCore() const
+{
+    // Allow dragging from selection area in details view.
+    if (m_layout == DetailsLayout && highlightEntireRow() && !isSelected()) {
+        QRectF result = m_iconRect | m_textRect;
+        return result;
     }
-
-    return m_textRect;
+    return selectionRectFull();
 }
 
 QRectF KStandardItemListWidget::expansionToggleRect() const
@@ -577,7 +572,6 @@ QRectF KStandardItemListWidget::selectionToggleRect() const
 {
     const_cast<KStandardItemListWidget *>(this)->triggerCacheRefreshing();
 
-    const QRectF widgetIconRect = iconRect();
     const int widgetIconSize = iconSize();
     int toggleSize = KIconLoader::SizeSmall;
     if (widgetIconSize >= KIconLoader::SizeEnormous) {
@@ -586,29 +580,11 @@ QRectF KStandardItemListWidget::selectionToggleRect() const
         toggleSize = KIconLoader::SizeSmallMedium;
     }
 
-    QPointF pos = widgetIconRect.topLeft();
-
-    // If the selection toggle has a very small distance to the
-    // widget borders, the size of the selection toggle will get
-    // increased to prevent an accidental clicking of the item
-    // when trying to hit the toggle.
-    const int widgetHeight = size().height();
-    const int widgetWidth = size().width();
-    const int minMargin = 2;
-
-    if (toggleSize + minMargin * 2 >= widgetHeight) {
-        pos.rx() -= (widgetHeight - toggleSize) / 2;
-        toggleSize = widgetHeight;
-        pos.setY(0);
-    }
-    if (toggleSize + minMargin * 2 >= widgetWidth) {
-        pos.ry() -= (widgetWidth - toggleSize) / 2;
-        toggleSize = widgetWidth;
-        pos.setX(0);
-    }
-
+    const int padding = styleOption().padding;
+    const QRectF selectionRectMinusPadding = selectionRectFull().adjusted(padding, padding, -padding, -padding);
+    QPointF pos = selectionRectMinusPadding.topLeft();
     if (QApplication::isRightToLeft()) {
-        pos.setX(widgetIconRect.right() - (pos.x() + toggleSize - widgetIconRect.left()));
+        pos.setX(selectionRectMinusPadding.right() - (pos.x() + toggleSize - selectionRectMinusPadding.left()));
     }
 
     return QRectF(pos, QSizeF(toggleSize, toggleSize));
@@ -647,7 +623,7 @@ void KStandardItemListWidget::startActivateSoonAnimation(int timeUntilActivation
     m_activateSoonAnimation->setEndValue(1.0);
     m_activateSoonAnimation->setDuration(timeUntilActivation);
 
-    const QVariant originalIconName{data()["iconName"]};
+    const QVariant originalIconName{value("iconName")};
     connect(m_activateSoonAnimation, &QVariantAnimation::valueChanged, this, [originalIconName, this](const QVariant &value) {
         auto progress = value.toFloat();
 
@@ -682,7 +658,7 @@ void KStandardItemListWidget::startActivateSoonAnimation(int timeUntilActivation
 
 bool KStandardItemListWidget::isIconControlledByActivateSoonAnimation() const
 {
-    return m_activateSoonAnimation && data()["iconName"] == "folder-open";
+    return m_activateSoonAnimation && value("iconName") == "folder-open";
 }
 
 KItemListWidgetInformant *KStandardItemListWidget::createInformant()
@@ -724,7 +700,11 @@ QFont KStandardItemListWidget::customizedFont(const QFont &baseFont) const
 
 QPalette::ColorRole KStandardItemListWidget::normalTextColorRole() const
 {
-    return QPalette::Text;
+    if (isPressed()) {
+        return QPalette::HighlightedText;
+    } else {
+        return QPalette::Text;
+    }
 }
 
 void KStandardItemListWidget::setTextColor(const QColor &color)
@@ -747,7 +727,7 @@ QColor KStandardItemListWidget::textColor(const QWidget &widget) const
     }
 
     const QPalette::ColorGroup group = isActiveWindow() && widget.hasFocus() ? QPalette::Active : QPalette::Inactive;
-    const QPalette::ColorRole role = isSelected() ? QPalette::HighlightedText : normalTextColorRole();
+    const QPalette::ColorRole role = normalTextColorRole();
     return styleOption().palette.color(group, role);
 }
 
@@ -1121,7 +1101,6 @@ void KStandardItemListWidget::updatePixmapCache()
                 // use a generic icon as fallback
                 iconName = QStringLiteral("unknown");
             }
-            const QStringList overlays = values["iconOverlays"].toStringList();
             const bool hasFocus = scene()->views()[0]->parentWidget()->hasFocus();
             m_pixmap = pixmapForIcon(iconName,
                                      QSize(maxIconWidth, maxIconHeight),
@@ -1136,7 +1115,6 @@ void KStandardItemListWidget::updatePixmapCache()
         }
 
         if (m_pixmap.isNull()) {
-            m_hoverPixmap = QPixmap();
             return;
         }
 
@@ -1147,17 +1125,6 @@ void KStandardItemListWidget::updatePixmapCache()
         if (m_isHidden) {
             KIconEffect::semiTransparent(m_pixmap);
         }
-
-        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);
-        }
     }
 
     int scaledIconSize = 0;
@@ -1205,15 +1172,6 @@ void KStandardItemListWidget::updatePixmapCache()
         const QSizeF squareIconSize(widgetIconSize, widgetIconSize);
         m_iconRect = QRectF(squareIconPos, squareIconSize);
     }
-
-    // Prepare the pixmap that is used when the item gets hovered
-    if (isHovered()) {
-        m_hoverPixmap = m_pixmap;
-        KIconEffect::toActive(m_hoverPixmap);
-    } else if (hoverOpacity() <= 0.0) {
-        // No hover animation is ongoing. Clear m_hoverPixmap to save memory.
-        m_hoverPixmap = QPixmap();
-    }
 }
 
 void KStandardItemListWidget::updateTextsCache()
@@ -1287,6 +1245,31 @@ void KStandardItemListWidget::updateTextsCache()
     }
 }
 
+QString KStandardItemListWidget::elideText(QString text, qreal maxWidth) const
+{
+    if (ContentDisplaySettings::elidingMode() == ContentDisplaySettings::ElidingMode::Middle) {
+        return m_customizedFontMetrics.elidedText(text, Qt::ElideMiddle, maxWidth);
+    }
+
+    if (ContentDisplaySettings::elidingMode() == ContentDisplaySettings::ElidingMode::Right) {
+        qsizetype lastDotPosition = text.lastIndexOf(".");
+        QString extension = text.mid(lastDotPosition);
+
+        if (m_customizedFontMetrics.horizontalAdvance(QStringLiteral("…") + extension) > maxWidth) {
+            extension = "";
+            lastDotPosition = text.size();
+        }
+
+        maxWidth -= m_customizedFontMetrics.horizontalAdvance(extension);
+        QString leftPart = m_customizedFontMetrics.elidedText(text.left(lastDotPosition), Qt::ElideRight, maxWidth);
+
+        return leftPart + extension;
+    }
+
+    Q_UNREACHABLE();
+    return text;
+}
+
 QString KStandardItemListWidget::escapeString(const QString &text) const
 {
     QString escaped(text);
@@ -1347,11 +1330,11 @@ void KStandardItemListWidget::updateIconsLayoutTextCache()
                 qreal lastLineWidth;
                 do {
                     QString lastTextLine = nameText.mid(line.textStart());
-                    lastTextLine = m_customizedFontMetrics.elidedText(lastTextLine, Qt::ElideMiddle, elidingWidth);
+                    lastTextLine = elideText(lastTextLine, elidingWidth);
                     const QString elidedText = nameText.left(line.textStart()) + lastTextLine;
                     nameTextInfo->staticText.setText(elidedText);
 
-                    lastLineWidth = m_customizedFontMetrics.horizontalAdvance(lastTextLine);
+                    lastLineWidth = m_customizedFontMetrics.boundingRect(lastTextLine).width();
 
                     // We do the text eliding in a loop with decreasing width (1 px / iteration)
                     // to avoid problems related to different width calculation code paths
@@ -1395,7 +1378,7 @@ void KStandardItemListWidget::updateIconsLayoutTextCache()
             textLine.setLineWidth(maxWidth);
             requiredWidth = textLine.naturalTextWidth();
             if (requiredWidth > maxWidth) {
-                const QString elidedText = m_customizedFontMetrics.elidedText(text, Qt::ElideMiddle, maxWidth);
+                const QString elidedText = m_customizedFontMetrics.elidedText(text, Qt::ElideRight, maxWidth);
                 textInfo->staticText.setText(elidedText);
                 requiredWidth = m_customizedFontMetrics.horizontalAdvance(elidedText);
             } else if (role == "rating") {
@@ -1447,8 +1430,13 @@ void KStandardItemListWidget::updateCompactLayoutTextCache()
         qreal requiredWidth = m_customizedFontMetrics.horizontalAdvance(text);
         if (requiredWidth > maxWidth) {
             requiredWidth = maxWidth;
-            const QString elidedText = m_customizedFontMetrics.elidedText(text, Qt::ElideMiddle, maxWidth);
-            textInfo->staticText.setText(elidedText);
+            if (role == "text") {
+                const QString elidedText = elideText(text, maxWidth);
+                textInfo->staticText.setText(elidedText);
+            } else {
+                const QString elidedText = m_customizedFontMetrics.elidedText(text, Qt::ElideRight, maxWidth);
+                textInfo->staticText.setText(elidedText);
+            }
         }
 
         textInfo->pos = QPointF(x, y);
@@ -1507,7 +1495,11 @@ void KStandardItemListWidget::updateDetailsLayoutTextCache()
         }
 
         if (requiredWidth > availableTextWidth) {
-            text = m_customizedFontMetrics.elidedText(text, Qt::ElideMiddle, availableTextWidth);
+            if (isTextRole) {
+                text = elideText(text, availableTextWidth);
+            } else {
+                text = m_customizedFontMetrics.elidedText(text, Qt::ElideRight, availableTextWidth);
+            }
             requiredWidth = m_customizedFontMetrics.horizontalAdvance(text);
         }
 
@@ -1537,7 +1529,7 @@ void KStandardItemListWidget::updateAdditionalInfoTextColor()
     } else if (isSelected() && hasFocus && (m_layout != DetailsLayout || m_highlightEntireRow)) {
         // The detail text color needs to match the main text (HighlightedText) for the same level
         // of readability. We short circuit early here to avoid interpolating with another color.
-        m_additionalInfoTextColor = styleOption().palette.color(QPalette::HighlightedText);
+        m_additionalInfoTextColor = styleOption().palette.color(normalTextColorRole());
         return;
     } else {
         c1 = styleOption().palette.text().color();