diff options
| -rw-r--r-- | src/kitemviews/kfileitemlistview.cpp | 18 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistview.cpp | 159 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistview.h | 29 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistviewlayouter.cpp | 8 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistviewlayouter_p.h | 9 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistwidget.cpp | 18 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistwidget.h | 8 |
7 files changed, 172 insertions, 77 deletions
diff --git a/src/kitemviews/kfileitemlistview.cpp b/src/kitemviews/kfileitemlistview.cpp index 25f7738bf..27ef7fdb5 100644 --- a/src/kitemviews/kfileitemlistview.cpp +++ b/src/kitemviews/kfileitemlistview.cpp @@ -324,9 +324,6 @@ void KFileItemListView::initializeItemListWidget(KItemListWidget* item) case DetailsLayout: fileItemListWidget->setLayout(KFileItemListWidget::DetailsLayout); break; default: Q_ASSERT(false); break; } - - fileItemListWidget->setAlternatingBackgroundColors(m_itemLayout == DetailsLayout && - visibleRoles().count() > 1); } bool KFileItemListView::itemSizeHintUpdateRequired(const QSet<QByteArray>& changedRoles) const @@ -379,20 +376,9 @@ void KFileItemListView::onScrollOffsetChanged(qreal current, qreal previous) void KFileItemListView::onVisibleRolesChanged(const QList<QByteArray>& current, const QList<QByteArray>& previous) { + Q_UNUSED(current); + Q_UNUSED(previous); applyRolesToModel(); - - if (m_itemLayout == DetailsLayout) { - // Only enable the alternating background colors if more than one role - // is visible - const int previousCount = previous.count(); - const int currentCount = current.count(); - if ((previousCount <= 1 && currentCount > 1) || (previousCount > 1 && currentCount <= 1)) { - const bool enabled = (currentCount > 1); - foreach (KItemListWidget* widget, visibleItemListWidgets()) { - widget->setAlternatingBackgroundColors(enabled); - } - } - } } void KFileItemListView::onStyleOptionChanged(const KItemListStyleOption& current, const KItemListStyleOption& previous) diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp index 907bf624d..527436725 100644 --- a/src/kitemviews/kitemlistview.cpp +++ b/src/kitemviews/kitemlistview.cpp @@ -156,9 +156,24 @@ void KItemListView::setItemSize(const QSizeF& itemSize) const bool animate = !changesItemGridLayout(m_layouter->size(), itemSize, m_layouter->itemMargin()); - + + const bool updateAlternateBackgrounds = (m_visibleRoles.count() > 1) && + (( m_itemSize.isEmpty() && !itemSize.isEmpty()) || + (!m_itemSize.isEmpty() && itemSize.isEmpty())); + m_itemSize = itemSize; + if (updateAlternateBackgrounds) { + // For an empty item size alternate backgrounds are drawn if more than + // one role is shown. Assure that the backgrounds for visible items are + // updated when changing the size in this context. + QHashIterator<int, KItemListWidget*> it(m_visibleItems); + while (it.hasNext()) { + it.next(); + updateAlternateBackgroundForWidget(it.value()); + } + } + if (itemSize.isEmpty()) { updateVisibleRolesSizes(); } else { @@ -238,12 +253,19 @@ void KItemListView::setVisibleRoles(const QList<QByteArray>& roles) const QList<QByteArray> previousRoles = m_visibleRoles; m_visibleRoles = roles; + const bool updateAlternateBackgrounds = m_itemSize.isEmpty() && + ((roles.count() > 1 && previousRoles.count() <= 1) || + (roles.count() <= 1 && previousRoles.count() > 1)); + QHashIterator<int, KItemListWidget*> it(m_visibleItems); while (it.hasNext()) { it.next(); KItemListWidget* widget = it.value(); widget->setVisibleRoles(roles); widget->setVisibleRolesSizes(m_stretchedVisibleRolesSizes); + if (updateAlternateBackgrounds) { + updateAlternateBackgroundForWidget(widget); + } } m_sizeHintResolver->clearCache(); @@ -785,9 +807,6 @@ void KItemListView::slotItemsInserted(const KItemRangeList& itemRanges) beginTransaction(); } - // Important: Don't read any m_layouter-property inside the for-loop in case if - // multiple ranges are given! m_layouter accesses m_sizeHintResolver which is - // updated in each loop-cycle and has only a consistent state after the loop. m_layouter->markAsDirty(); int previouslyInsertedCount = 0; @@ -823,11 +842,12 @@ void KItemListView::slotItemsInserted(const KItemRangeList& itemRanges) for (int i = itemsToMove.count() - 1; i >= 0; --i) { KItemListWidget* widget = m_visibleItems.value(itemsToMove[i]); Q_ASSERT(widget); + const int newIndex = widget->index() + count; if (hasMultipleRanges) { - setWidgetIndex(widget, widget->index() + count); + setWidgetIndex(widget, newIndex); } else { // Try to animate the moving of the item - moveWidgetToIndex(widget, widget->index() + count); + moveWidgetToIndex(widget, newIndex); } } @@ -861,6 +881,12 @@ void KItemListView::slotItemsInserted(const KItemRangeList& itemRanges) } if (hasMultipleRanges) { +#ifndef QT_NO_DEBUG + // Important: Don't read any m_layouter-property inside the for-loop in case if + // multiple ranges are given! m_layouter accesses m_sizeHintResolver which is + // updated in each loop-cycle and has only a consistent state after the loop. + Q_ASSERT(m_layouter->isDirty()); +#endif m_endTransactionAnimationHint = NoAnimation; endTransaction(); updateSiblingsInformation(); @@ -876,9 +902,6 @@ void KItemListView::slotItemsRemoved(const KItemRangeList& itemRanges) beginTransaction(); } - // Important: Don't read any m_layouter-property inside the for-loop in case if - // multiple ranges are given! m_layouter accesses m_sizeHintResolver which is - // updated in each loop-cycle and has only a consistent state after the loop. m_layouter->markAsDirty(); for (int i = itemRanges.count() - 1; i >= 0; --i) { @@ -959,6 +982,12 @@ void KItemListView::slotItemsRemoved(const KItemRangeList& itemRanges) } if (hasMultipleRanges) { +#ifndef QT_NO_DEBUG + // Important: Don't read any m_layouter-property inside the for-loop in case if + // multiple ranges are given! m_layouter accesses m_sizeHintResolver which is + // updated in each loop-cycle and has only a consistent state after the loop. + Q_ASSERT(m_layouter->isDirty()); +#endif m_endTransactionAnimationHint = NoAnimation; endTransaction(); updateSiblingsInformation(); @@ -981,9 +1010,6 @@ void KItemListView::slotItemsMoved(const KItemRange& itemRange, const QList<int> KItemListWidget* widget = m_visibleItems.value(index); if (widget) { updateWidgetProperties(widget, index); - if (m_grouped) { - updateGroupHeaderForWidget(widget); - } initializeItemListWidget(widget); } } @@ -1048,6 +1074,17 @@ void KItemListView::slotGroupedSortingChanged(bool current) Q_ASSERT(m_visibleGroups.isEmpty()); } + if (useAlternateBackgrounds()) { + // Changing the group mode requires to update the alternate backgrounds + // as with the enabled group mode the altering is done on base of the first + // group item. + QHashIterator<int, KItemListWidget*> it(m_visibleItems); + while (it.hasNext()) { + it.next(); + updateAlternateBackgroundForWidget(it.value()); + } + } + doLayout(NoAnimation); } @@ -1077,13 +1114,11 @@ void KItemListView::slotCurrentChanged(int current, int previous) KItemListWidget* previousWidget = m_visibleItems.value(previous, 0); if (previousWidget) { - Q_ASSERT(previousWidget->isCurrent()); previousWidget->setCurrent(false); } KItemListWidget* currentWidget = m_visibleItems.value(current, 0); if (currentWidget) { - Q_ASSERT(!currentWidget->isCurrent()); currentWidget->setCurrent(true); } } @@ -1406,10 +1441,8 @@ void KItemListView::doLayout(LayoutAnimationHint hint, int changedIndex, int cha const int oldIndex = reusableItems.takeLast(); widget = m_visibleItems.value(oldIndex); setWidgetIndex(widget, i); - - if (m_grouped) { - updateGroupHeaderForWidget(widget); - } + updateWidgetProperties(widget, i); + initializeItemListWidget(widget); } else { // No reusable KItemListWidget instance is available, create a new one widget = createWidget(i); @@ -1626,14 +1659,9 @@ KItemListWidget* KItemListView::createWidget(int index) KItemListWidget* widget = m_widgetCreator->create(this); widget->setFlag(QGraphicsItem::ItemStacksBehindParent); - updateWidgetProperties(widget, index); m_visibleItems.insert(index, widget); m_visibleCells.insert(index, Cell()); - - if (m_grouped) { - updateGroupHeaderForWidget(widget); - } - + updateWidgetProperties(widget, index); initializeItemListWidget(widget); return widget; } @@ -1654,16 +1682,13 @@ void KItemListView::recycleWidget(KItemListWidget* widget) void KItemListView::setWidgetIndex(KItemListWidget* widget, int index) { const int oldIndex = widget->index(); - m_visibleItems.remove(oldIndex); m_visibleCells.remove(oldIndex); - updateWidgetProperties(widget, index); - m_visibleItems.insert(index, widget); m_visibleCells.insert(index, Cell()); - initializeItemListWidget(widget); + widget->setIndex(index); } void KItemListView::moveWidgetToIndex(KItemListWidget* widget, int index) @@ -1701,11 +1726,15 @@ void KItemListView::updateWidgetProperties(KItemListWidget* widget, int index) widget->setCurrent(index == selectionManager->currentItem()); widget->setSelected(selectionManager->isSelected(index)); widget->setHovered(false); - widget->setAlternatingBackgroundColors(false); widget->setEnabledSelectionToggle(enabledSelectionToggles()); widget->setIndex(index); widget->setData(m_model->data(index)); widget->setSiblingsInformation(QBitArray()); + updateAlternateBackgroundForWidget(widget); + + if (m_grouped) { + updateGroupHeaderForWidget(widget); + } } void KItemListView::updateGroupHeaderForWidget(KItemListWidget* widget) @@ -1734,21 +1763,9 @@ void KItemListView::updateGroupHeaderForWidget(KItemListWidget* widget) } Q_ASSERT(groupHeader->parentItem() == widget); - // Determine the shown data for the header by doing a binary - // search in the groups-list - int min = 0; - int max = groups.count() - 1; - int mid = 0; - do { - mid = (min + max) / 2; - if (index > groups.at(mid).first) { - min = mid + 1; - } else { - max = mid - 1; - } - } while (groups.at(mid).first != index && min <= max); - - groupHeader->setData(groups.at(mid).second); + const int groupIndex = groupIndexForItem(index); + Q_ASSERT(groupIndex >= 0); + groupHeader->setData(groups.at(groupIndex).second); groupHeader->setRole(model()->sortRole()); groupHeader->setStyleOption(m_styleOption); groupHeader->setScrollOrientation(scrollOrientation()); @@ -1803,6 +1820,60 @@ void KItemListView::updateVisibleGroupHeaders() } } +int KItemListView::groupIndexForItem(int index) const +{ + Q_ASSERT(m_grouped); + + const QList<QPair<int, QVariant> > groups = model()->groups(); + if (groups.isEmpty()) { + return -1; + } + + int min = 0; + int max = groups.count() - 1; + int mid = 0; + do { + mid = (min + max) / 2; + if (index > groups[mid].first) { + min = mid + 1; + } else { + max = mid - 1; + } + } while (groups[mid].first != index && min <= max); + + if (min > max) { + while (groups[mid].first > index && mid > 0) { + --mid; + } + } + + return mid; +} + +void KItemListView::updateAlternateBackgroundForWidget(KItemListWidget* widget) +{ + bool enabled = useAlternateBackgrounds(); + if (enabled) { + const int index = widget->index(); + enabled = (index & 0x1) > 0; + if (m_grouped) { + const int groupIndex = groupIndexForItem(index); + if (groupIndex >= 0) { + const QList<QPair<int, QVariant> > groups = model()->groups(); + const int indexOfFirstGroupItem = groups[groupIndex].first; + const int relativeIndex = index - indexOfFirstGroupItem; + enabled = (relativeIndex & 0x1) == 0; + } + } + } + widget->setAlternateBackground(enabled); +} + +bool KItemListView::useAlternateBackgrounds() const +{ + return m_itemSize.isEmpty() && m_visibleRoles.count() > 1; +} + QHash<QByteArray, qreal> KItemListView::headerRolesWidths() const { QHash<QByteArray, qreal> rolesWidths; diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h index d524dbdf4..17b7b8880 100644 --- a/src/kitemviews/kitemlistview.h +++ b/src/kitemviews/kitemlistview.h @@ -396,14 +396,15 @@ private: void recycleWidget(KItemListWidget* widget); /** - * Changes the index of the widget to \a index. The cell-information - * for the widget gets reset and will be updated in the next doLayout(). + * Changes the index of the widget to \a index and assures a consistent + * update for m_visibleItems and m_visibleCells. The cell-information + * for the new index will not be updated and be initialized as empty cell. */ void setWidgetIndex(KItemListWidget* widget, int index); /** * Changes the index of the widget to \a index. In opposite to - * setWidgetIndex() the cell-information of the widget gets updated. + * setWidgetIndex() the cell-information for the widget gets updated. * This update gives doLayout() the chance to animate the moving * of the item visually (see moveWidget()). */ @@ -421,7 +422,7 @@ private: void updateWidgetProperties(KItemListWidget* widget, int index); /** - * Helper method for createWidget() and setWidgetIndex() to create or update + * Helper method for updateWidgetPropertes() to create or update * the itemlist group-header. */ void updateGroupHeaderForWidget(KItemListWidget* widget); @@ -446,6 +447,26 @@ private: void updateVisibleGroupHeaders(); /** + * @return Index for the item in the list returned by KItemModelBase::groups() + * that represents the group where the item with the index \a index + * belongs to. -1 is returned if no groups are available. + */ + int groupIndexForItem(int index) const; + + /** + * Updates the alternateBackground-property of the widget dependent + * on the state of useAlternateBackgrounds() and the grouping state. + */ + void updateAlternateBackgroundForWidget(KItemListWidget* widget); + + /** + * @return True if alternate backgrounds should be used for the items. + * This is the case if an empty item-size is given and if there + * is more than one visible role. + */ + bool useAlternateBackgrounds() const; + + /** * @return The widths of each visible role that is shown in the KItemListHeader. */ QHash<QByteArray, qreal> headerRolesWidths() const; diff --git a/src/kitemviews/kitemlistviewlayouter.cpp b/src/kitemviews/kitemlistviewlayouter.cpp index 744914929..d8b5796ec 100644 --- a/src/kitemviews/kitemlistviewlayouter.cpp +++ b/src/kitemviews/kitemlistviewlayouter.cpp @@ -340,6 +340,14 @@ void KItemListViewLayouter::markAsDirty() m_dirty = true; } + +#ifndef QT_NO_DEBUG + bool KItemListViewLayouter::isDirty() + { + return m_dirty; + } +#endif + void KItemListViewLayouter::doLayout() { if (m_dirty) { diff --git a/src/kitemviews/kitemlistviewlayouter_p.h b/src/kitemviews/kitemlistviewlayouter_p.h index 017f520fe..0d7c0d040 100644 --- a/src/kitemviews/kitemlistviewlayouter_p.h +++ b/src/kitemviews/kitemlistviewlayouter_p.h @@ -139,6 +139,15 @@ public: void markAsDirty(); +#ifndef QT_NO_DEBUG + /** + * @return True if the layouter has been marked as dirty and hence has + * not called yet doLayout(). Is enabled only in the debugging + * mode, as it is not useful to check the dirty state otherwise. + */ + bool isDirty(); +#endif + private: void doLayout(); void updateVisibleIndexes(); diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp index 94eed6840..9d58a283e 100644 --- a/src/kitemviews/kitemlistwidget.cpp +++ b/src/kitemviews/kitemlistwidget.cpp @@ -40,7 +40,7 @@ KItemListWidget::KItemListWidget(QGraphicsItem* parent) : m_selected(false), m_current(false), m_hovered(false), - m_alternatingBackgroundColors(false), + m_alternateBackground(false), m_enabledSelectionToggle(false), m_data(), m_visibleRoles(), @@ -105,7 +105,7 @@ void KItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsItem* o { Q_UNUSED(option); - if (m_alternatingBackgroundColors && (m_index & 0x1)) { + if (m_alternateBackground) { const QColor backgroundColor = m_styleOption.palette.color(QPalette::AlternateBase); const QRectF backgroundRect(0, 0, size().width(), size().height()); painter->fillRect(backgroundRect, backgroundColor); @@ -276,18 +276,18 @@ bool KItemListWidget::isHovered() const return m_hovered; } -void KItemListWidget::setAlternatingBackgroundColors(bool enable) +void KItemListWidget::setAlternateBackground(bool enable) { - if (m_alternatingBackgroundColors != enable) { - m_alternatingBackgroundColors = enable; - alternatingBackgroundColorsChanged(enable); + if (m_alternateBackground != enable) { + m_alternateBackground = enable; + alternateBackgroundChanged(enable); update(); } } -bool KItemListWidget::alternatingBackgroundColors() const +bool KItemListWidget::alternateBackground() const { - return m_alternatingBackgroundColors; + return m_alternateBackground; } void KItemListWidget::setEnabledSelectionToggle(bool enable) @@ -381,7 +381,7 @@ void KItemListWidget::hoveredChanged(bool hovered) Q_UNUSED(hovered); } -void KItemListWidget::alternatingBackgroundColorsChanged(bool enabled) +void KItemListWidget::alternateBackgroundChanged(bool enabled) { Q_UNUSED(enabled); } diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h index 20efa7c94..84bd15fa5 100644 --- a/src/kitemviews/kitemlistwidget.h +++ b/src/kitemviews/kitemlistwidget.h @@ -82,8 +82,8 @@ public: void setHovered(bool hovered); bool isHovered() const; - void setAlternatingBackgroundColors(bool enable); - bool alternatingBackgroundColors() const; + void setAlternateBackground(bool enable); + bool alternateBackground() const; void setEnabledSelectionToggle(bool enabled); bool enabledSelectionToggle() const; @@ -138,7 +138,7 @@ protected: virtual void currentChanged(bool current); virtual void selectedChanged(bool selected); virtual void hoveredChanged(bool hovered); - virtual void alternatingBackgroundColorsChanged(bool enabled); + virtual void alternateBackgroundChanged(bool enabled); virtual void siblingsInformationChanged(const QBitArray& current, const QBitArray& previous); virtual void resizeEvent(QGraphicsSceneResizeEvent* event); @@ -164,7 +164,7 @@ private: bool m_selected; bool m_current; bool m_hovered; - bool m_alternatingBackgroundColors; + bool m_alternateBackground; bool m_enabledSelectionToggle; QHash<QByteArray, QVariant> m_data; QList<QByteArray> m_visibleRoles; |
