]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Calculate all item size hints at once.
authorEmmanuel Pescosta <emmanuelpescosta099@gmail.com>
Sun, 12 Jan 2014 22:24:00 +0000 (23:24 +0100)
committerEmmanuel Pescosta <emmanuelpescosta099@gmail.com>
Sun, 12 Jan 2014 22:24:00 +0000 (23:24 +0100)
The speed up is really small, but theses changes are mostly straightforward and make the code a bit nicer - break
the KStandardItemListWidgetInformant::itemSizeHint beast into three smaller functions.

FIXED-IN: 4.13
REVIEW: 112979

src/kitemviews/kitemlistview.cpp
src/kitemviews/kitemlistview.h
src/kitemviews/kitemlistwidget.h
src/kitemviews/kstandarditemlistwidget.cpp
src/kitemviews/kstandarditemlistwidget.h
src/kitemviews/private/kitemlistsizehintresolver.cpp
src/kitemviews/private/kitemlistsizehintresolver.h
src/kitemviews/private/kitemlistviewlayouter.cpp
src/kitemviews/private/kitemlistviewlayouter.h

index 7f497210cdd5eb5abc8603319c950f3f374ad9ef..38ce63af0adf839cbfee987fc33fcc1363fc9f01 100644 (file)
@@ -460,9 +460,9 @@ int KItemListView::lastVisibleIndex() const
     return m_layouter->lastVisibleIndex();
 }
 
-QSizeF KItemListView::itemSizeHint(int index) const
+void KItemListView::calculateItemSizeHints(QVector<QSizeF>& sizeHints) const
 {
-    return widgetCreator()->itemSizeHint(index, this);
+    widgetCreator()->calculateItemSizeHints(sizeHints, this);
 }
 
 void KItemListView::setSupportsItemExpanding(bool supportsExpanding)
index dbe9230867610975e17e0b9607cd3f9e27dc03ae..f39e73a979c7242590108f45618dec1992754a42 100644 (file)
@@ -194,12 +194,12 @@ public:
     int lastVisibleIndex() const;
 
     /**
-     * @return Required size for the item with the index \p index.
+     * @return Required size for all items in the model.
      *         The returned value might be larger than KItemListView::itemSize().
      *         In this case the layout grid will be stretched to assure an
      *         unclipped item.
      */
-    QSizeF itemSizeHint(int index) const;
+    void calculateItemSizeHints(QVector<QSizeF>& sizeHints) const;
 
     /**
      * If set to true, items having child-items can be expanded to show the child-items as
@@ -802,7 +802,7 @@ public:
 
     virtual void recycle(KItemListWidget* widget);
 
-    virtual QSizeF itemSizeHint(int index, const KItemListView* view) const = 0;
+    virtual void calculateItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const = 0;
 
     virtual qreal preferredRoleColumnWidth(const QByteArray& role,
                                            int index,
@@ -821,7 +821,7 @@ public:
 
     virtual KItemListWidget* create(KItemListView* view);
 
-    virtual QSizeF itemSizeHint(int index, const KItemListView* view) const;
+    virtual void calculateItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const;
 
     virtual qreal preferredRoleColumnWidth(const QByteArray& role,
                                            int index,
@@ -854,9 +854,9 @@ KItemListWidget* KItemListWidgetCreator<T>::create(KItemListView* view)
 }
 
 template<class T>
-QSizeF KItemListWidgetCreator<T>::itemSizeHint(int index, const KItemListView* view) const
+void KItemListWidgetCreator<T>::calculateItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const
 {
-    return m_informant->itemSizeHint(index, view);
+    return m_informant->calculateItemSizeHints(sizeHints, view);
 }
 
 template<class T>
index 55181faa863c993e9362a464c4ca93b1b2ef2dc4..954629ddde80ac96fca4684d2ddb1aed50c3072d 100644 (file)
@@ -49,7 +49,7 @@ public:
     KItemListWidgetInformant();
     virtual ~KItemListWidgetInformant();
 
-    virtual QSizeF itemSizeHint(int index, const KItemListView* view) const = 0;
+    virtual void calculateItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const = 0;
 
     virtual qreal preferredRoleColumnWidth(const QByteArray& role,
                                            int index,
index acdf839aca58923f1c0bcac8dddf86f9ef0ae045..9a9a734ed058e5c158a6745d2a920b2402639083 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,
@@ -181,6 +122,107 @@ QString KStandardItemListWidgetInformant::roleText(const QByteArray& role,
     return values.value(role).toString();
 }
 
+void KStandardItemListWidgetInformant::calculateIconsLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const
+{
+    const KItemListStyleOption& option = view->styleOption();
+    const QFont& font = 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 maxTextHeight = option.maxTextSize.height();
+    const qreal additionalRolesSpacing = additionalRolesCount * option.fontMetrics.lineSpacing();
+    const qreal spacingAndIconHeight = option.iconSize + option.padding * 3;
+
+    QTextOption textOption(Qt::AlignHCenter);
+    textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
+
+    for (int index = 0; index < sizeHints.count(); ++index) {
+        if (!sizeHints.at(index).isEmpty()) {
+            continue;
+        }
+
+        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;
+        while ((line = layout.createLine()).isValid()) {
+            line.setLineWidth(maxWidth);
+            line.naturalTextWidth();
+            textHeight += line.height();
+        }
+        layout.endLayout();
+
+        // Add one line for each additional information
+        textHeight += additionalRolesSpacing;
+
+        if (maxTextHeight > 0 && textHeight > maxTextHeight) {
+            textHeight = maxTextHeight;
+        }
+
+        sizeHints[index] = QSizeF(itemWidth, textHeight + spacingAndIconHeight);
+    }
+}
+
+void KStandardItemListWidgetInformant::calculateCompactLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const
+{
+    const KItemListStyleOption& option = view->styleOption();
+    const QFontMetrics& fontMetrics = 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.maxTextSize.width();
+    const qreal paddingAndIconWidth = option.padding * 4 + option.iconSize;
+    const qreal height = option.padding * 2 + qMax(option.iconSize, (1 + additionalRolesCount) * option.fontMetrics.lineSpacing());
+
+    for (int index = 0; index < sizeHints.count(); ++index) {
+        if (!sizeHints.at(index).isEmpty()) {
+            continue;
+        }
+
+        // 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),
index 7dd93b2b819babd5e48271ba47a1d89339b166bb..ca198c36b5c4693fdbf7a1a00d9d3e7f8c383380 100644 (file)
@@ -38,7 +38,7 @@ public:
     KStandardItemListWidgetInformant();
     virtual ~KStandardItemListWidgetInformant();
 
-    virtual QSizeF itemSizeHint(int index, const KItemListView* view) const;
+    virtual void calculateItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const;
 
     virtual qreal preferredRoleColumnWidth(const QByteArray& role,
                                            int index,
@@ -61,6 +61,10 @@ protected:
     virtual QString roleText(const QByteArray& role,
                              const QHash<QByteArray, QVariant>& values) const;
 
+    void calculateIconsLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const;
+    void calculateCompactLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const;
+    void calculateDetailsLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const;
+
     friend class KStandardItemListWidget; // Accesses roleText()
 };
 
index 0e2286b453a9c539358528318288c9e695de1b6c..029beddf9d54ab78c7bae80a08ba153ea205c817 100644 (file)
@@ -23,7 +23,8 @@
 
 KItemListSizeHintResolver::KItemListSizeHintResolver(const KItemListView* itemListView) :
     m_itemListView(itemListView),
-    m_sizeHintCache()
+    m_sizeHintCache(),
+    m_needsResolving(false)
 {
 }
 
@@ -31,14 +32,10 @@ KItemListSizeHintResolver::~KItemListSizeHintResolver()
 {
 }
 
-QSizeF KItemListSizeHintResolver::sizeHint(int index) const
+QSizeF KItemListSizeHintResolver::sizeHint(int index)
 {
-    QSizeF size = m_sizeHintCache.at(index);
-    if (size.isEmpty()) {
-        size = m_itemListView->itemSizeHint(index);
-        m_sizeHintCache[index] = size;
-    }
-    return size;
+    updateCache();
+    return m_sizeHintCache.at(index);
 }
 
 void KItemListSizeHintResolver::itemsInserted(const KItemRangeList& itemRanges)
@@ -77,6 +74,8 @@ void KItemListSizeHintResolver::itemsInserted(const KItemRangeList& itemRanges)
         }
     }
 
+    m_needsResolving = true;
+
     Q_ASSERT(m_sizeHintCache.count() == m_itemListView->model()->count());
 }
 
@@ -135,9 +134,20 @@ void KItemListSizeHintResolver::itemsChanged(int index, int count, const QSet<QB
         ++index;
         --count;
     }
+
+    m_needsResolving = true;
 }
 
 void KItemListSizeHintResolver::clearCache()
 {
     m_sizeHintCache.fill(QSizeF());
+    m_needsResolving = true;
+}
+
+void KItemListSizeHintResolver::updateCache()
+{
+    if (m_needsResolving) {
+        m_itemListView->calculateItemSizeHints(m_sizeHintCache);
+        m_needsResolving = false;
+    }
 }
index 486f9b6313f0771842f932c6a2e8e0a6b13e618c..86580bf7bf661cb6a1fd4c49b629e2242d59dc3f 100644 (file)
@@ -36,7 +36,7 @@ class LIBDOLPHINPRIVATE_EXPORT KItemListSizeHintResolver
 public:
     KItemListSizeHintResolver(const KItemListView* itemListView);
     virtual ~KItemListSizeHintResolver();
-    QSizeF sizeHint(int index) const;
+    QSizeF sizeHint(int index);
 
     void itemsInserted(const KItemRangeList& itemRanges);
     void itemsRemoved(const KItemRangeList& itemRanges);
@@ -44,10 +44,12 @@ public:
     void itemsChanged(int index, int count, const QSet<QByteArray>& roles);
 
     void clearCache();
+    void updateCache();
 
 private:
     const KItemListView* m_itemListView;
     mutable QVector<QSizeF> m_sizeHintCache;
+    bool m_needsResolving;
 };
 
 #endif
index 90e8a6d0f3096ba5dd577a091c8c28d6cbee90e0..73f3d6182153d1c4eca8c5ec5fb04afbc9e4991b 100644 (file)
@@ -209,7 +209,7 @@ const KItemModelBase* KItemListViewLayouter::model() const
     return m_model;
 }
 
-void KItemListViewLayouter::setSizeHintResolver(const KItemListSizeHintResolver* sizeHintResolver)
+void KItemListViewLayouter::setSizeHintResolver(KItemListSizeHintResolver* sizeHintResolver)
 {
     if (m_sizeHintResolver != sizeHintResolver) {
         m_sizeHintResolver = sizeHintResolver;
index 19b14796de7e9a9893d6278d59970461ad632d81..5ae4724116900e684d571890de6a182dcb34679e 100644 (file)
@@ -103,7 +103,7 @@ public:
     void setModel(const KItemModelBase* model);
     const KItemModelBase* model() const;
 
-    void setSizeHintResolver(const KItemListSizeHintResolver* sizeHintResolver);
+    void setSizeHintResolver(KItemListSizeHintResolver* sizeHintResolver);
     const KItemListSizeHintResolver* sizeHintResolver() const;
 
     /**
@@ -205,7 +205,7 @@ private:
     QSizeF m_itemMargin;
     qreal m_headerHeight;
     const KItemModelBase* m_model;
-    const KItemListSizeHintResolver* m_sizeHintResolver;
+    KItemListSizeHintResolver* m_sizeHintResolver;
 
     qreal m_scrollOffset;
     qreal m_maximumScrollOffset;