]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kstandarditemlistwidget.cpp
Merge remote-tracking branch 'origin/KDE/4.11'
[dolphin.git] / src / kitemviews / kstandarditemlistwidget.cpp
index 3dccfcc7dd52ac738581f9c3b65975709ba14067..483517ecc6f08de7f44eda242cc7fc77233d212b 100644 (file)
@@ -194,7 +194,8 @@ KStandardItemListWidget::KStandardItemListWidget(KItemListWidgetInformant* infor
     m_additionalInfoTextColor(),
     m_overlay(),
     m_rating(),
-    m_roleEditor(0)
+    m_roleEditor(0),
+    m_oldRoleEditor(0)
 {
 }
 
@@ -203,7 +204,13 @@ KStandardItemListWidget::~KStandardItemListWidget()
     qDeleteAll(m_textInfo);
     m_textInfo.clear();
 
-    delete m_roleEditor;
+    if (m_roleEditor) {
+        m_roleEditor->deleteLater();
+    }
+
+    if (m_oldRoleEditor) {
+        m_oldRoleEditor->deleteLater();
+    }
 }
 
 void KStandardItemListWidget::setLayout(Layout layout)
@@ -247,22 +254,52 @@ void KStandardItemListWidget::paint(QPainter* painter, const QStyleOptionGraphic
 
     const KItemListStyleOption& itemListStyleOption = styleOption();
     if (isHovered()) {
-        // Blend the unhovered and hovered pixmap if the hovering
-        // animation is ongoing
         if (hoverOpacity() < 1.0) {
-            drawPixmap(painter, m_pixmap);
-        }
+            /*
+             * Linear interpolation between m_pixmap and m_hoverPixmap.
+             *
+             * Note that this cannot be achieved by painting m_hoverPixmap over
+             * m_pixmap, even if the opacities are adjusted. For details see
+             * https://git.reviewboard.kde.org/r/109614/
+             */
+            // Paint pixmap1 so that pixmap1 = m_pixmap * (1.0 - hoverOpacity())
+            QPixmap pixmap1(m_pixmap.size());
+            pixmap1.fill(Qt::transparent);
+            {
+                QPainter p(&pixmap1);
+                p.setOpacity(1.0 - hoverOpacity());
+                p.drawPixmap(0, 0, m_pixmap);
+            }
 
-        const qreal opacity = painter->opacity();
-        painter->setOpacity(hoverOpacity() * opacity);
-        drawPixmap(painter, m_hoverPixmap);
-        painter->setOpacity(opacity);
+            // Paint pixmap2 so that pixmap2 = m_hoverPixmap * hoverOpacity()
+            QPixmap pixmap2(pixmap1.size());
+            pixmap2.fill(Qt::transparent);
+            {
+                QPainter p(&pixmap2);
+                p.setOpacity(hoverOpacity());
+                p.drawPixmap(0, 0, m_hoverPixmap);
+            }
+
+            // Paint pixmap2 on pixmap1 using CompositionMode_Plus
+            // Now pixmap1 = pixmap2 + m_pixmap * (1.0 - hoverOpacity())
+            //             = m_hoverPixmap * hoverOpacity() + m_pixmap * (1.0 - hoverOpacity())
+            {
+                QPainter p(&pixmap1);
+                p.setCompositionMode(QPainter::CompositionMode_Plus);
+                p.drawPixmap(0, 0, pixmap2);
+            }
+
+            // Finally paint pixmap1 on the widget
+            drawPixmap(painter, pixmap1);
+        } else {
+            drawPixmap(painter, m_hoverPixmap);
+        }
     } else {
         drawPixmap(painter, m_pixmap);
     }
 
     painter->setFont(m_customizedFont);
-    painter->setPen(m_isHidden ? m_additionalInfoTextColor : textColor());
+    painter->setPen(textColor());
     const TextInfo* textInfo = m_textInfo.value("text");
 
     if (!textInfo) {
@@ -316,6 +353,9 @@ void KStandardItemListWidget::paint(QPainter* painter, const QStyleOptionGraphic
     painter->setPen(Qt::green);
     painter->drawRect(m_iconRect);
 
+    painter->setPen(Qt::blue);
+    painter->drawRect(m_textRect);
+
     painter->setPen(Qt::red);
     painter->drawText(QPointF(0, m_customizedFontMetrics.height()), QString::number(index()));
     painter->drawRect(rect());
@@ -491,8 +531,12 @@ void KStandardItemListWidget::setTextColor(const QColor& color)
 
 QColor KStandardItemListWidget::textColor() const
 {
-    if (m_customTextColor.isValid() && !isSelected()) {
-        return m_customTextColor;
+    if (!isSelected()) {
+        if (m_isHidden) {
+            return m_additionalInfoTextColor;
+        } else if (m_customTextColor.isValid()) {
+            return m_customTextColor;
+        }
     }
 
     const QPalette::ColorGroup group = isActiveWindow() ? QPalette::Active : QPalette::Inactive;
@@ -606,11 +650,16 @@ void KStandardItemListWidget::editedRoleChanged(const QByteArray& current, const
         if (m_roleEditor) {
             emit roleEditingCanceled(index(), current, data().value(current));
 
-            disconnect(m_roleEditor, SIGNAL(roleEditingCanceled(int,QByteArray,QVariant)),
-                       this, SLOT(slotRoleEditingCanceled(int,QByteArray,QVariant)));
-            disconnect(m_roleEditor, SIGNAL(roleEditingFinished(int,QByteArray,QVariant)),
-                       this, SLOT(slotRoleEditingFinished(int,QByteArray,QVariant)));
-            m_roleEditor->deleteLater();
+            disconnect(m_roleEditor, SIGNAL(roleEditingCanceled(QByteArray,QVariant)),
+                       this, SLOT(slotRoleEditingCanceled(QByteArray,QVariant)));
+            disconnect(m_roleEditor, SIGNAL(roleEditingFinished(QByteArray,QVariant)),
+                       this, SLOT(slotRoleEditingFinished(QByteArray,QVariant)));
+
+            if (m_oldRoleEditor) {
+                m_oldRoleEditor->deleteLater();
+            }
+            m_oldRoleEditor = m_roleEditor;
+            m_roleEditor->hide();
             m_roleEditor = 0;
         }
         return;
@@ -621,7 +670,6 @@ void KStandardItemListWidget::editedRoleChanged(const QByteArray& current, const
     const TextInfo* textInfo = m_textInfo.value("text");
 
     m_roleEditor = new KItemListRoleEditor(parent);
-    m_roleEditor->setIndex(index());
     m_roleEditor->setRole(current);
     m_roleEditor->setFont(styleOption().font);
 
@@ -640,10 +688,10 @@ void KStandardItemListWidget::editedRoleChanged(const QByteArray& current, const
         m_roleEditor->setTextCursor(cursor);
     }
 
-    connect(m_roleEditor, SIGNAL(roleEditingCanceled(int,QByteArray,QVariant)),
-            this, SLOT(slotRoleEditingCanceled(int,QByteArray,QVariant)));
-    connect(m_roleEditor, SIGNAL(roleEditingFinished(int,QByteArray,QVariant)),
-            this, SLOT(slotRoleEditingFinished(int,QByteArray,QVariant)));
+    connect(m_roleEditor, SIGNAL(roleEditingCanceled(QByteArray,QVariant)),
+            this, SLOT(slotRoleEditingCanceled(QByteArray,QVariant)));
+    connect(m_roleEditor, SIGNAL(roleEditingFinished(QByteArray,QVariant)),
+            this, SLOT(slotRoleEditingFinished(QByteArray,QVariant)));
 
     // Adjust the geometry of the editor
     QRectF rect = roleEditingRect(current);
@@ -704,21 +752,19 @@ void KStandardItemListWidget::slotCutItemsChanged()
     }
 }
 
-void KStandardItemListWidget::slotRoleEditingCanceled(int index,
-                                                      const QByteArray& role,
+void KStandardItemListWidget::slotRoleEditingCanceled(const QByteArray& role,
                                                       const QVariant& value)
 {
     closeRoleEditor();
-    emit roleEditingCanceled(index, role, value);
+    emit roleEditingCanceled(index(), role, value);
     setEditedRole(QByteArray());
 }
 
-void KStandardItemListWidget::slotRoleEditingFinished(int index,
-                                                      const QByteArray& role,
+void KStandardItemListWidget::slotRoleEditingFinished(const QByteArray& role,
                                                       const QVariant& value)
 {
     closeRoleEditor();
-    emit roleEditingFinished(index, role, value);
+    emit roleEditingFinished(index(), role, value);
     setEditedRole(QByteArray());
 }
 
@@ -749,7 +795,6 @@ void KStandardItemListWidget::updateExpansionArea()
 {
     if (m_supportsItemExpanding) {
         const QHash<QByteArray, QVariant> values = data();
-        Q_ASSERT(values.contains("expandedParentsCount"));
         const int expandedParentsCount = values.value("expandedParentsCount", 0).toInt();
         if (expandedParentsCount >= 0) {
             const qreal widgetHeight = size().height();
@@ -797,29 +842,14 @@ void KStandardItemListWidget::updatePixmapCache()
                 // use a generic icon as fallback
                 iconName = QLatin1String("unknown");
             }
-            m_pixmap = pixmapForIcon(iconName, maxIconHeight);
+            const QStringList overlays = values["iconOverlays"].toStringList();
+            m_pixmap = pixmapForIcon(iconName, overlays, maxIconHeight);
         } else if (m_pixmap.width() != maxIconWidth || m_pixmap.height() != maxIconHeight) {
             // A custom pixmap has been applied. Assure that the pixmap
             // is scaled to the maximum available size.
             KPixmapModifier::scale(m_pixmap, QSize(maxIconWidth, maxIconHeight));
         }
 
-        const QStringList overlays = values["iconOverlays"].toStringList();
-
-        // Strangely KFileItem::overlays() returns empty string-values, so
-        // we need to check first whether an overlay must be drawn at all.
-        // 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) {
-            if (!overlay.isEmpty()) {
-                // There is at least one overlay, draw all overlays above m_pixmap
-                // and cancel the check
-                KIconLoader::global()->drawOverlays(overlays, m_pixmap, KIconLoader::Desktop);
-                break;
-            }
-        }
-
         if (m_isCut) {
             KIconEffect* effect = KIconLoader::global()->iconEffect();
             m_pixmap = effect->apply(m_pixmap, KIconLoader::Desktop, KIconLoader::DisabledState);
@@ -832,7 +862,7 @@ void KStandardItemListWidget::updatePixmapCache()
         if (isSelected()) {
             const QColor color = palette().brush(QPalette::Normal, QPalette::Highlight).color();
             QImage image = m_pixmap.toImage();
-            KIconEffect::colorize(image, color, 1.0f);
+            KIconEffect::colorize(image, color, 0.8f);
             m_pixmap = QPixmap::fromImage(image);
         }
     }
@@ -1108,7 +1138,7 @@ void KStandardItemListWidget::updateCompactLayoutTextCache()
         y += lineSpacing;
     }
 
-    m_textRect = QRectF(x - option.padding, 0, maximumRequiredTextWidth + 2 * option.padding, widgetHeight);
+    m_textRect = QRectF(x - 2 * option.padding, 0, maximumRequiredTextWidth + 3 * option.padding, widgetHeight);
 }
 
 void KStandardItemListWidget::updateDetailsLayoutTextCache()
@@ -1166,8 +1196,8 @@ void KStandardItemListWidget::updateDetailsLayoutTextCache()
             const qreal textWidth = option.extendedSelectionRegion
                                     ? size().width() - textInfo->pos.x()
                                     : requiredWidth + 2 * option.padding;
-            m_textRect = QRectF(textInfo->pos.x() - option.padding, 0,
-                                textWidth, size().height());
+            m_textRect = QRectF(textInfo->pos.x() - 2 * option.padding, 0,
+                                textWidth + option.padding, 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
@@ -1265,23 +1295,28 @@ QRectF KStandardItemListWidget::roleEditingRect(const QByteArray& role) const
 
 void KStandardItemListWidget::closeRoleEditor()
 {
+    disconnect(m_roleEditor, SIGNAL(roleEditingCanceled(QByteArray,QVariant)),
+               this, SLOT(slotRoleEditingCanceled(QByteArray,QVariant)));
+    disconnect(m_roleEditor, SIGNAL(roleEditingFinished(QByteArray,QVariant)),
+               this, SLOT(slotRoleEditingFinished(QByteArray,QVariant)));
+
     if (m_roleEditor->hasFocus()) {
         // If the editing was not ended by a FocusOut event, we have
         // to transfer the keyboard focus back to the KItemListContainer.
         scene()->views()[0]->parentWidget()->setFocus();
     }
 
-    disconnect(m_roleEditor, SIGNAL(roleEditingCanceled(int,QByteArray,QVariant)),
-               this, SLOT(slotRoleEditingCanceled(int,QByteArray,QVariant)));
-    disconnect(m_roleEditor, SIGNAL(roleEditingFinished(int,QByteArray,QVariant)),
-               this, SLOT(slotRoleEditingFinished(int,QByteArray,QVariant)));
-    m_roleEditor->deleteLater();
+    if (m_oldRoleEditor) {
+        m_oldRoleEditor->deleteLater();
+    }
+    m_oldRoleEditor = m_roleEditor;
+    m_roleEditor->hide();
     m_roleEditor = 0;
 }
 
-QPixmap KStandardItemListWidget::pixmapForIcon(const QString& name, int size)
+QPixmap KStandardItemListWidget::pixmapForIcon(const QString& name, const QStringList& overlays, int size)
 {
-    const QString key = "KStandardItemListWidget:" % name  % ":" % QString::number(size);
+    const QString key = "KStandardItemListWidget:" % name % ":" % overlays.join(":") % ":" % QString::number(size);
     QPixmap pixmap;
 
     if (!QPixmapCache::find(key, pixmap)) {
@@ -1311,6 +1346,20 @@ QPixmap KStandardItemListWidget::pixmapForIcon(const QString& name, int size)
             KPixmapModifier::scale(pixmap, QSize(size, size));
         }
 
+        // Strangely KFileItem::overlays() returns empty string-values, so
+        // we need to check first whether an overlay must be drawn at all.
+        // 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) {
+            if (!overlay.isEmpty()) {
+                // There is at least one overlay, draw all overlays above m_pixmap
+                // and cancel the check
+                KIconLoader::global()->drawOverlays(overlays, pixmap, KIconLoader::Desktop);
+                break;
+            }
+        }
+
         QPixmapCache::insert(key, pixmap);
     }