]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kstandarditemlistwidget.cpp
Merge branch 'KDE/4.13'
[dolphin.git] / src / kitemviews / kstandarditemlistwidget.cpp
index acdf839aca58923f1c0bcac8dddf86f9ef0ae045..03722699700549ba237f4691e11c7a6c2ebfdab4 100644 (file)
@@ -55,84 +55,25 @@ KStandardItemListWidgetInformant::~KStandardItemListWidgetInformant()
 {
 }
 
-QSizeF KStandardItemListWidgetInformant::itemSizeHint(int index, const KItemListView* view) const
+void KStandardItemListWidgetInformant::calculateItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const
 {
-    const KItemListStyleOption& option = view->styleOption();
-    const int additionalRolesCount = qMax(view->visibleRoles().count() - 1, 0);
-
     switch (static_cast<const KStandardItemListView*>(view)->itemLayout()) {
-    case KStandardItemListWidget::IconsLayout: {
-        const QString text = KStringHandler::preProcessWrap(itemText(index, view));
-
-        const qreal itemWidth = view->itemSize().width();
-        const qreal maxWidth = itemWidth - 2 * option.padding;
-        QTextLine line;
-
-        // Calculate the number of lines required for wrapping the name
-        QTextOption textOption(Qt::AlignHCenter);
-        textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
-
-        qreal textHeight = 0;
-        QTextLayout layout(text, option.font);
-        layout.setTextOption(textOption);
-        layout.beginLayout();
-        while ((line = layout.createLine()).isValid()) {
-            line.setLineWidth(maxWidth);
-            line.naturalTextWidth();
-            textHeight += line.height();
-        }
-        layout.endLayout();
-
-        // Add one line for each additional information
-        textHeight += additionalRolesCount * option.fontMetrics.lineSpacing();
-
-        const qreal maxTextHeight = option.maxTextSize.height();
-        if (maxTextHeight > 0 && textHeight > maxTextHeight) {
-            textHeight = maxTextHeight;
-        }
-
-        return QSizeF(itemWidth, textHeight + option.iconSize + option.padding * 3);
-    }
-
-    case KStandardItemListWidget::CompactLayout: {
-        // For each row exactly one role is shown. Calculate the maximum required width that is necessary
-        // to show all roles without horizontal clipping.
-        qreal maximumRequiredWidth = 0.0;
-
-        const QList<QByteArray>& visibleRoles = view->visibleRoles();
-        const bool showOnlyTextRole = (visibleRoles.count() == 1) && (visibleRoles.first() == "text");
-
-        if (showOnlyTextRole) {
-            maximumRequiredWidth = option.fontMetrics.width(itemText(index, view));
-        } else {
-            const QHash<QByteArray, QVariant> values = view->model()->data(index);
-            foreach (const QByteArray& role, view->visibleRoles()) {
-                const QString text = roleText(role, values);
-                const qreal requiredWidth = option.fontMetrics.width(text);
-                maximumRequiredWidth = qMax(maximumRequiredWidth, requiredWidth);
-            }
-        }
+    case KStandardItemListWidget::IconsLayout:
+        calculateIconsLayoutItemSizeHints(sizeHints, view);
+        break;
 
-        qreal width = option.padding * 4 + option.iconSize + maximumRequiredWidth;
-        const qreal maxWidth = option.maxTextSize.width();
-        if (maxWidth > 0 && width > maxWidth) {
-            width = maxWidth;
-        }
-        const qreal height = option.padding * 2 + qMax(option.iconSize, (1 + additionalRolesCount) * option.fontMetrics.lineSpacing());
-        return QSizeF(width, height);
-    }
+    case KStandardItemListWidget::CompactLayout:
+        calculateCompactLayoutItemSizeHints(sizeHints, view);
+        break;
 
-    case KStandardItemListWidget::DetailsLayout: {
-        const qreal height = option.padding * 2 + qMax(option.iconSize, option.fontMetrics.height());
-        return QSizeF(-1, height);
-    }
+    case KStandardItemListWidget::DetailsLayout:
+        calculateDetailsLayoutItemSizeHints(sizeHints, view);
+        break;
 
     default:
         Q_ASSERT(false);
         break;
     }
-
-    return QSize();
 }
 
 qreal KStandardItemListWidgetInformant::preferredRoleColumnWidth(const QByteArray& role,
@@ -145,16 +86,22 @@ qreal KStandardItemListWidgetInformant::preferredRoleColumnWidth(const QByteArra
     const QString text = roleText(role, values);
     qreal width = KStandardItemListWidget::columnPadding(option);
 
+    const QFontMetrics& normalFontMetrics = option.fontMetrics;
+    const QFontMetrics linkFontMetrics(customizedFontForLinks(option.font));
+
     if (role == "rating") {
         width += KStandardItemListWidget::preferredRatingSize(option).width();
     } else {
-        width += option.fontMetrics.width(text);
+        // 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);
 
         if (role == "text") {
             if (view->supportsItemExpanding()) {
                 // Increase the width by the expansion-toggle and the current expansion level
                 const int expandedParentsCount = values.value("expandedParentsCount", 0).toInt();
-                const qreal height = option.padding * 2 + qMax(option.iconSize, option.fontMetrics.height());
+                const qreal height = option.padding * 2 + qMax(option.iconSize, fontMetrics.height());
                 width += (expandedParentsCount + 1) * height;
             }
 
@@ -171,6 +118,11 @@ QString KStandardItemListWidgetInformant::itemText(int index, const KItemListVie
     return view->model()->data(index).value("text").toString();
 }
 
+bool KStandardItemListWidgetInformant::itemIsLink(int index, const KItemListView* view) const
+{
+    return false;
+}
+
 QString KStandardItemListWidgetInformant::roleText(const QByteArray& role,
                                                    const QHash<QByteArray, QVariant>& values) const
 {
@@ -181,6 +133,123 @@ QString KStandardItemListWidgetInformant::roleText(const QByteArray& role,
     return values.value(role).toString();
 }
 
+QFont KStandardItemListWidgetInformant::customizedFontForLinks(const QFont& baseFont) const
+{
+    return baseFont;
+}
+
+void KStandardItemListWidgetInformant::calculateIconsLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const
+{
+    const KItemListStyleOption& option = view->styleOption();
+    const QFont& normalFont = option.font;
+    const int additionalRolesCount = qMax(view->visibleRoles().count() - 1, 0);
+
+    const qreal itemWidth = view->itemSize().width();
+    const qreal maxWidth = itemWidth - 2 * option.padding;
+    const qreal additionalRolesSpacing = additionalRolesCount * option.fontMetrics.lineSpacing();
+    const qreal spacingAndIconHeight = option.iconSize + option.padding * 3;
+
+    const QFont linkFont = customizedFontForLinks(normalFont);
+
+    QTextOption textOption(Qt::AlignHCenter);
+    textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
+
+    for (int index = 0; index < sizeHints.count(); ++index) {
+        if (!sizeHints.at(index).isEmpty()) {
+            continue;
+        }
+
+        // If the current item is a link, we use the customized link font instead of the normal font.
+        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);
+        layout.setTextOption(textOption);
+        layout.beginLayout();
+        QTextLine line;
+        int lineCount = 0;
+        while ((line = layout.createLine()).isValid()) {
+            line.setLineWidth(maxWidth);
+            line.naturalTextWidth();
+            textHeight += line.height();
+
+            ++lineCount;
+            if (lineCount == option.maxTextLines) {
+                break;
+            }
+        }
+        layout.endLayout();
+
+        // Add one line for each additional information
+        textHeight += additionalRolesSpacing;
+
+        sizeHints[index] = QSizeF(itemWidth, textHeight + spacingAndIconHeight);
+    }
+}
+
+void KStandardItemListWidgetInformant::calculateCompactLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const
+{
+    const KItemListStyleOption& option = view->styleOption();
+    const QFontMetrics& normalFontMetrics = option.fontMetrics;
+    const int additionalRolesCount = qMax(view->visibleRoles().count() - 1, 0);
+
+    const QList<QByteArray>& visibleRoles = view->visibleRoles();
+    const bool showOnlyTextRole = (visibleRoles.count() == 1) && (visibleRoles.first() == "text");
+    const qreal maxWidth = option.maxTextWidth;
+    const qreal paddingAndIconWidth = option.padding * 4 + option.iconSize;
+    const qreal height = option.padding * 2 + qMax(option.iconSize, (1 + additionalRolesCount) * normalFontMetrics.lineSpacing());
+
+    const QFontMetrics linkFontMetrics(customizedFontForLinks(option.font));
+
+    for (int index = 0; index < sizeHints.count(); ++index) {
+        if (!sizeHints.at(index).isEmpty()) {
+            continue;
+        }
+
+        // If the 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;
+
+        // For each row exactly one role is shown. Calculate the maximum required width that is necessary
+        // to show all roles without horizontal clipping.
+        qreal maximumRequiredWidth = 0.0;
+
+        if (showOnlyTextRole) {
+            maximumRequiredWidth = fontMetrics.width(itemText(index, view));
+        } else {
+            const QHash<QByteArray, QVariant>& values = view->model()->data(index);
+            foreach (const QByteArray& role, visibleRoles) {
+                const QString& text = roleText(role, values);
+                const qreal requiredWidth = fontMetrics.width(text);
+                maximumRequiredWidth = qMax(maximumRequiredWidth, requiredWidth);
+            }
+        }
+
+        qreal width = paddingAndIconWidth + maximumRequiredWidth;
+        if (maxWidth > 0 && width > maxWidth) {
+            width = maxWidth;
+        }
+
+        sizeHints[index] = QSizeF(width, height);
+    }
+}
+
+void KStandardItemListWidgetInformant::calculateDetailsLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const
+{
+    const KItemListStyleOption& option = view->styleOption();
+    const qreal height = option.padding * 2 + qMax(option.iconSize, option.fontMetrics.height());
+
+    for (int index = 0; index < sizeHints.count(); ++index) {
+        if (!sizeHints.at(index).isEmpty()) {
+            continue;
+        }
+
+        sizeHints[index] = QSizeF(-1, height);
+    }
+}
+
 KStandardItemListWidget::KStandardItemListWidget(KItemListWidgetInformant* informant, QGraphicsItem* parent) :
     KItemListWidget(informant, parent),
     m_isCut(false),
@@ -589,6 +658,12 @@ void KStandardItemListWidget::dataChanged(const QHash<QByteArray, QVariant>& cur
         dirtyRoles = roles;
     }
 
+    // The URL might have changed (i.e., if the sort order of the items has
+    // been changed). Therefore, the "is cut" state must be updated.
+    KFileItemClipboard* clipboard = KFileItemClipboard::instance();
+    const KUrl itemUrl = data().value("url").value<KUrl>();
+    m_isCut = clipboard->isCut(itemUrl);
+
     // The icon-state might depend from other roles and hence is
     // marked as dirty whenever a role has been changed
     dirtyRoles.insert("iconPixmap");
@@ -1024,9 +1099,6 @@ void KStandardItemListWidget::updateIconsLayoutTextCache()
     qreal nameHeight = 0;
     QTextLine line;
 
-    const int additionalRolesCount = qMax(visibleRoles().count() - 1, 0);
-    const int maxNameLines = (option.maxTextSize.height() / int(lineSpacing)) - additionalRolesCount;
-
     QTextLayout layout(nameTextInfo->staticText.text(), m_customizedFont);
     layout.setTextOption(nameTextInfo->staticText.textOption());
     layout.beginLayout();
@@ -1037,7 +1109,7 @@ void KStandardItemListWidget::updateIconsLayoutTextCache()
         nameHeight += line.height();
 
         ++nameLineIndex;
-        if (nameLineIndex == maxNameLines) {
+        if (nameLineIndex == option.maxTextLines) {
             // The maximum number of textlines has been reached. If this is
             // the case provide an elided text if necessary.
             const int textLength = line.textStart() + line.textLength();
@@ -1059,6 +1131,7 @@ void KStandardItemListWidget::updateIconsLayoutTextCache()
     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 -