]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kfileitemlistwidget.cpp
Allow resizing of columns by the user
[dolphin.git] / src / kitemviews / kfileitemlistwidget.cpp
index a8fe36c08c18acd9a6e6444c6617b18cf05f18e1..49c5db5fdaf9655e37c25588a7da51da3c74d016 100644 (file)
@@ -56,7 +56,9 @@ KFileItemListWidget::KFileItemListWidget(QGraphicsItem* parent) :
     m_textBoundingRect(),
     m_sortedVisibleRoles(),
     m_expansionArea(),
-    m_additionalInfoTextColor()
+    m_customTextColor(),
+    m_additionalInfoTextColor(),
+    m_overlay()
 {
     for (int i = 0; i < TextIdCount; ++i) {
         m_text[i].setTextFormat(Qt::PlainText);
@@ -86,9 +88,7 @@ void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsIte
 {
     KItemListWidget::paint(painter, option, widget);
 
-    if (m_dirtyContent || m_dirtyLayout) {
-        const_cast<KFileItemListWidget*>(this)->updateCache();
-    }
+    const_cast<KFileItemListWidget*>(this)->triggerCacheRefreshing();
 
     // Draw expansion toggle '>' or 'V'
     if (m_isDir && !m_expansionArea.isEmpty()) {
@@ -116,7 +116,7 @@ void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsIte
     }
 
     painter->setFont(itemListStyleOption.font);
-    painter->setPen(itemListStyleOption.palette.text().color());
+    painter->setPen(textColor());
     painter->drawStaticText(m_textPos[Name], m_text[Name]);
 
     painter->setPen(m_additionalInfoTextColor);
@@ -135,6 +135,8 @@ void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsIte
 
 QRectF KFileItemListWidget::iconBoundingRect() const
 {
+    const_cast<KFileItemListWidget*>(this)->triggerCacheRefreshing();
+
     QRectF bounds = m_hoverPixmapRect;
     const qreal margin = styleOption().margin;
     bounds.adjust(-margin, -margin, margin, margin);
@@ -143,14 +145,52 @@ QRectF KFileItemListWidget::iconBoundingRect() const
 
 QRectF KFileItemListWidget::textBoundingRect() const
 {
+    const_cast<KFileItemListWidget*>(this)->triggerCacheRefreshing();
     return m_textBoundingRect;
 }
 
 QRectF KFileItemListWidget::expansionToggleRect() const
 {
+    const_cast<KFileItemListWidget*>(this)->triggerCacheRefreshing();
     return m_isDir ? m_expansionArea : QRectF();
 }
 
+void KFileItemListWidget::invalidateCache()
+{
+    m_dirtyLayout = true;
+    m_dirtyContent = true;
+}
+
+void KFileItemListWidget::refreshCache()
+{
+}
+
+void KFileItemListWidget::setTextColor(const QColor& color)
+{
+    if (color != m_customTextColor) {
+        m_customTextColor = color;
+        updateAdditionalInfoTextColor();
+        update();
+    }
+}
+
+QColor KFileItemListWidget::textColor() const
+{
+    return m_customTextColor.isValid() ? m_customTextColor : styleOption().palette.text().color();
+}
+
+void KFileItemListWidget::setOverlay(const QPixmap& overlay)
+{
+    m_overlay = overlay;
+    m_dirtyContent = true;
+    update();
+}
+
+QPixmap KFileItemListWidget::overlay() const
+{
+    return m_overlay;
+}
+
 void KFileItemListWidget::dataChanged(const QHash<QByteArray, QVariant>& current,
                                       const QSet<QByteArray>& roles)
 {
@@ -159,7 +199,7 @@ void KFileItemListWidget::dataChanged(const QHash<QByteArray, QVariant>& current
 
     QSet<QByteArray> dirtyRoles;
     if (roles.isEmpty()) {
-        dirtyRoles = visibleRoles().keys().toSet();
+        dirtyRoles = visibleRoles().toSet();
         dirtyRoles.insert("iconPixmap");
         dirtyRoles.insert("iconName");
     } else {
@@ -173,33 +213,12 @@ void KFileItemListWidget::dataChanged(const QHash<QByteArray, QVariant>& current
     }
 }
 
-void KFileItemListWidget::visibleRolesChanged(const QHash<QByteArray, int>& current,
-                                              const QHash<QByteArray, int>& previous)
+void KFileItemListWidget::visibleRolesChanged(const QList<QByteArray>& current,
+                                              const QList<QByteArray>& previous)
 {
     KItemListWidget::visibleRolesChanged(current, previous);
+    m_sortedVisibleRoles = current;
     m_dirtyLayout = true;
-
-    // Cache the roles sorted into m_sortedVisibleRoles:
-    const int visibleRolesCount = current.count();
-    m_sortedVisibleRoles.clear();
-    m_sortedVisibleRoles.reserve(visibleRolesCount);
-    for (int i = 0; i < visibleRolesCount; ++i) {
-        m_sortedVisibleRoles.append(QByteArray());
-    }
-
-    QHashIterator<QByteArray, int> it(current);
-    while (it.hasNext()) {
-        it.next();
-
-        const int index = it.value();
-        if (index < 0 || index >= visibleRolesCount || !m_sortedVisibleRoles.at(index).isEmpty()) {
-            kWarning() << "The visible roles have an invalid sort order.";
-            break;
-        }
-
-        const QByteArray& role = it.key();
-        m_sortedVisibleRoles[index] = role;
-    }
 }
 
 void KFileItemListWidget::visibleRolesSizesChanged(const QHash<QByteArray, QSizeF>& current,
@@ -213,18 +232,7 @@ void KFileItemListWidget::styleOptionChanged(const KItemListStyleOption& current
                                              const KItemListStyleOption& previous)
 {
     KItemListWidget::styleOptionChanged(current, previous);
-
-    // For the color of the additional info the inactive text color
-    // is not used as this might lead to unreadable text for some color schemes. Instead
-    // the text color is slightly mixed with the background color.
-    const QColor c1 = current.palette.text().color();
-    const QColor c2 = current.palette.background().color();
-    const int p1 = 70;
-    const int p2 = 100 - p1;
-    m_additionalInfoTextColor = QColor((c1.red()   * p1 + c2.red()   * p2) / 100,
-                                       (c1.green() * p1 + c2.green() * p2) / 100,
-                                       (c1.blue()  * p1 + c2.blue()  * p2) / 100);
-
+    updateAdditionalInfoTextColor();
     m_dirtyLayout = true;
 }
 
@@ -240,12 +248,14 @@ void KFileItemListWidget::resizeEvent(QGraphicsSceneResizeEvent* event)
     m_dirtyLayout = true;
 }
 
-void KFileItemListWidget::updateCache()
+void KFileItemListWidget::triggerCacheRefreshing()
 {
-    if (index() < 0) {
+    if ((!m_dirtyContent && !m_dirtyLayout) || index() < 0) {
         return;
     }
 
+    refreshCache();
+
     m_isDir = data()["isDir"].toBool();
 
     updateExpansionArea();
@@ -348,6 +358,10 @@ void KFileItemListWidget::updatePixmapCache()
 
         Q_ASSERT(m_pixmap.height() == iconHeight);
     }
+    if (!m_overlay.isNull()) {
+        QPainter painter(&m_pixmap);
+        painter.drawPixmap(0, m_pixmap.height() - m_overlay.height(), m_overlay);
+    }
 
     m_scaledPixmapSize = QSize(scaledIconHeight, scaledIconHeight);
 
@@ -564,7 +578,9 @@ void KFileItemListWidget::updateDetailsLayoutTextCache()
     const int scaledIconSize = widgetHeight - 2 * option.margin;
     const int fontHeight = option.fontMetrics.height();
 
-    qreal x = m_expansionArea.right() + option.margin * 3 + scaledIconSize;
+    const qreal columnMargin = option.margin * 3;
+    const qreal firstColumnInc = m_expansionArea.right() + option.margin * 2 + scaledIconSize;
+    qreal x = firstColumnInc;
     const qreal y = qMax(qreal(option.margin), (widgetHeight - fontHeight) / 2);
 
     foreach (const QByteArray& role, m_sortedVisibleRoles) {
@@ -574,7 +590,7 @@ void KFileItemListWidget::updateDetailsLayoutTextCache()
         m_text[textId].setText(text);
 
         const qreal requiredWidth = option.fontMetrics.width(text);
-        m_textPos[textId] = QPointF(x, y);
+        m_textPos[textId] = QPointF(x + columnMargin, y);
 
         const qreal columnWidth = visibleRolesSizes().value(role, QSizeF(0, 0)).width();
         x += columnWidth;
@@ -582,16 +598,16 @@ void KFileItemListWidget::updateDetailsLayoutTextCache()
         switch (textId) {
         case Name: {
             m_textBoundingRect = QRectF(m_textPos[textId].x() - option.margin, 0,
-                                         requiredWidth + 2 * option.margin, size().height());
+                                        requiredWidth + 2 * option.margin, 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
-            x -= m_expansionArea.right();
+            x -= firstColumnInc;
             break;
         }
         case Size:
             // The values for the size should be right aligned
-            m_textPos[textId].rx() += columnWidth - requiredWidth - 2 * option.margin;
+            m_textPos[textId].rx() += columnWidth - requiredWidth - 2 * columnMargin;
             break;
 
         default:
@@ -600,6 +616,20 @@ void KFileItemListWidget::updateDetailsLayoutTextCache()
     }
 }
 
+void KFileItemListWidget::updateAdditionalInfoTextColor()
+{
+    // For the color of the additional info the inactive text color
+    // is not used as this might lead to unreadable text for some color schemes. Instead
+    // the text color is slightly mixed with the background color.
+    const QColor c1 = textColor();
+    const QColor c2 = styleOption().palette.background().color();
+    const int p1 = 70;
+    const int p2 = 100 - p1;
+    m_additionalInfoTextColor = QColor((c1.red()   * p1 + c2.red()   * p2) / 100,
+                                       (c1.green() * p1 + c2.green() * p2) / 100,
+                                       (c1.blue()  * p1 + c2.blue()  * p2) / 100);
+}
+
 QString KFileItemListWidget::roleText(TextId textId, const QVariant& roleValue) const
 {
     QString text;