void KItemListView::setItemOffset(qreal offset)
{
+ if (m_layouter->itemOffset() == offset) {
+ return;
+ }
+
m_layouter->setItemOffset(offset);
if (m_header) {
m_header->setPos(-offset, 0);
}
- if (!m_layoutTimer->isActive()) {
- doLayout(NoAnimation);
- }
+
+ // Don't check whether the m_layoutTimer is active: Changing the
+ // item offset must always trigger a synchronous layout, otherwise
+ // the smooth-scrolling might get jerky.
+ doLayout(NoAnimation);
}
qreal KItemListView::itemOffset() const
return;
}
- if (m_model->count() > 0) {
- prepareLayoutForIncreasedItemCount(rect.size(), LayouterSize);
+ const QSizeF newSize = rect.size();
+ if (m_itemSize.isEmpty()) {
+ // The item size is dynamic:
+ // Changing the geometry does not require to do an expensive
+ // update of the visible-roles sizes, only the stretched sizes
+ // need to be adjusted to the new size.
+ updateStretchedVisibleRolesSizes();
+
+ if (m_useHeaderWidths) {
+ QSizeF dynamicItemSize = m_layouter->itemSize();
+
+ if (m_itemSize.width() < 0) {
+ const qreal requiredWidth = visibleRolesSizesWidthSum();
+ if (newSize.width() > requiredWidth) {
+ dynamicItemSize.setWidth(newSize.width());
+ }
+ const qreal headerWidth = qMax(newSize.width(), requiredWidth);
+ m_header->resize(headerWidth, m_header->size().height());
+ }
+
+ if (m_itemSize.height() < 0) {
+ const qreal requiredHeight = visibleRolesSizesHeightSum();
+ if (newSize.height() > requiredHeight) {
+ dynamicItemSize.setHeight(newSize.height());
+ }
+ // TODO: KItemListHeader is not prepared for vertical alignment
+ }
+
+ m_layouter->setItemSize(dynamicItemSize);
+ }
+
+ // Triggering a synchronous layout is fine from a performance point of view,
+ // as with dynamic item sizes no moving animation must be done.
+ m_layouter->setSize(newSize);
+ doLayout(Animation);
} else {
- m_layouter->setSize(rect.size());
- }
+ // The item size is not dynamic and most probably the geometry change results
+ // in animated position changes of the items. Trigger an asynchronous relayout
+ // with m_layoutTimer to prevent performance bottlenecks.
+ if (m_model->count() > 0) {
+ prepareLayoutForIncreasedItemCount(newSize, LayouterSize);
+ } else {
+ m_layouter->setSize(newSize);
+ }
- if (!m_layoutTimer->isActive()) {
- m_layoutTimer->start();
+ if (!m_layoutTimer->isActive()) {
+ m_layoutTimer->start();
+ }
}
-
- // Changing the geometry does not require to do an expensive
- // update of the visible-roles sizes, only the stretched sizes
- // need to be adjusted to the new size.
- updateStretchedVisibleRolesSizes();
}
int KItemListView::itemAt(const QPointF& pos) const
bool KItemListView::isAboveSelectionToggle(int index, const QPointF& pos) const
{
+ if (!m_enabledSelectionToggles) {
+ return false;
+ }
+
const KItemListWidget* widget = m_visibleItems.value(index);
if (widget) {
const QRectF selectionToggleRect = widget->selectionToggleRect();
return m_visibleItems.values();
}
-void KItemListView::resizeEvent(QGraphicsSceneResizeEvent* event)
-{
- QGraphicsWidget::resizeEvent(event);
- if (m_itemSize.isEmpty() && m_useHeaderWidths) {
- QSizeF dynamicItemSize = m_layouter->itemSize();
- const QSizeF newSize = event->newSize();
-
- if (m_itemSize.width() < 0) {
- const qreal requiredWidth = visibleRolesSizesWidthSum();
- if (newSize.width() > requiredWidth) {
- dynamicItemSize.setWidth(newSize.width());
- }
- const qreal headerWidth = qMax(newSize.width(), requiredWidth);
- m_header->resize(headerWidth, m_header->size().height());
- }
-
- if (m_itemSize.height() < 0) {
- const qreal requiredHeight = visibleRolesSizesHeightSum();
- if (newSize.height() > requiredHeight) {
- dynamicItemSize.setHeight(newSize.height());
- }
- // TODO: KItemListHeader is not prepared for vertical alignment
- }
-
- m_layouter->setItemSize(dynamicItemSize);
- }
-}
-
void KItemListView::slotItemsInserted(const KItemRangeList& itemRanges)
{
updateVisibleRolesSizes(itemRanges);
}
m_layouter->markAsDirty();
- if (m_model->count() == count && maximumScrollOffset() > size().height()) {
- const int scrollBarExtent = style()->pixelMetric(QStyle::PM_ScrollBarExtent);
- QSizeF layouterSize = m_layouter->size();
- if (scrollOrientation() == Qt::Vertical) {
- layouterSize.rwidth() -= scrollBarExtent;
- } else {
- layouterSize.rheight() -= scrollBarExtent;
+ if (m_model->count() == count && m_activeTransactions == 0) {
+ // Check whether a scrollbar is required to show the inserted items. In this case
+ // the size of the layouter will be decreased before calling doLayout(): This prevents
+ // an unnecessary temporary animation due to the geometry change of the inserted scrollbar.
+ const bool verticalScrollOrientation = (scrollOrientation() == Qt::Vertical);
+ const bool decreaseLayouterSize = ( verticalScrollOrientation && maximumScrollOffset() > size().height()) ||
+ (!verticalScrollOrientation && maximumScrollOffset() > size().width());
+ if (decreaseLayouterSize) {
+ const int scrollBarExtent = style()->pixelMetric(QStyle::PM_ScrollBarExtent);
+ QSizeF layouterSize = m_layouter->size();
+ if (verticalScrollOrientation) {
+ layouterSize.rwidth() -= scrollBarExtent;
+ } else {
+ layouterSize.rheight() -= scrollBarExtent;
+ }
+ m_layouter->setSize(layouterSize);
}
- m_layouter->setSize(layouterSize);
}
if (!hasMultipleRanges) {
m_layouter->markAsDirty();
if (!hasMultipleRanges) {
+ // The decrease-layout-size optimization in KItemListView::slotItemsInserted()
+ // assumes an updated geometry. If items are removed during an active transaction,
+ // the transaction will be temporary deactivated so that doLayout() triggers a
+ // geometry update if necessary.
+ const int activeTransactions = m_activeTransactions;
+ m_activeTransactions = 0;
doLayout(Animation, index, -count);
+ m_activeTransactions = activeTransactions;
}
}