#include "kitemlistcontroller.h"
#include "kitemlistheader.h"
-#include "kitemlistheaderwidget_p.h"
-#include "kitemlistrubberband_p.h"
#include "kitemlistselectionmanager.h"
-#include "kitemlistsizehintresolver_p.h"
-#include "kitemlistviewlayouter_p.h"
-#include "kitemlistviewanimation_p.h"
#include "kitemlistwidget.h"
+#include "private/kitemlistheaderwidget.h"
+#include "private/kitemlistrubberband.h"
+#include "private/kitemlistsizehintresolver.h"
+#include "private/kitemlistviewlayouter.h"
+#include "private/kitemlistviewanimation.h"
+
#include <KDebug>
#include <QCursor>
m_layouter->setItemOffset(offset);
if (m_headerWidget->isVisible()) {
- m_headerWidget->setPos(-offset, 0);
+ m_headerWidget->setOffset(offset);
}
// Don't check whether the m_layoutTimer is active: Changing the
const QSizeF newSize = rect.size();
if (m_itemSize.isEmpty()) {
+ m_headerWidget->resize(rect.width(), m_headerWidget->size().height());
if (m_headerWidget->automaticColumnResizing()) {
applyAutomaticColumnWidths();
} else {
const QSizeF dynamicItemSize(qMax(newSize.width(), requiredWidth),
m_itemSize.height());
m_layouter->setItemSize(dynamicItemSize);
- m_headerWidget->resize(dynamicItemSize.width(), m_headerWidget->size().height());
}
// Triggering a synchronous layout is fine from a performance point of view,
QSizeF KItemListView::itemSizeHint(int index) const
{
- Q_UNUSED(index);
- return itemSize();
-}
-
-QHash<QByteArray, qreal> KItemListView::preferredColumnWidths(const KItemRangeList& itemRanges) const
-{
- Q_UNUSED(itemRanges);
- return QHash<QByteArray, qreal>();
+ return m_widgetCreator->itemSizeHint(index, this);
}
void KItemListView::setSupportsItemExpanding(bool supportsExpanding)
void KItemListView::setHeaderVisible(bool visible)
{
if (visible && !m_headerWidget->isVisible()) {
+ QStyleOptionHeader option;
+ const QSize headerSize = style()->sizeFromContents(QStyle::CT_HeaderSection,
+ &option, QSize());
+
m_headerWidget->setPos(0, 0);
+ m_headerWidget->resize(size().width(), headerSize.height());
m_headerWidget->setModel(m_model);
m_headerWidget->setColumns(m_visibleRoles);
m_headerWidget->setZValue(1);
connect(m_headerWidget, SIGNAL(sortRoleChanged(QByteArray,QByteArray)),
this, SIGNAL(sortRoleChanged(QByteArray,QByteArray)));
- m_layouter->setHeaderHeight(m_headerWidget->size().height());
+ m_layouter->setHeaderHeight(headerSize.height());
m_headerWidget->setVisible(true);
} else if (!visible && m_headerWidget->isVisible()) {
disconnect(m_headerWidget, SIGNAL(columnWidthChanged(QByteArray,qreal,qreal)),
m_layouter->markAsDirty();
+ int removedItemsCount = 0;
+ for (int i = 0; i < itemRanges.count(); ++i) {
+ removedItemsCount += itemRanges[i].count;
+ }
+
for (int i = itemRanges.count() - 1; i >= 0; --i) {
- const KItemRange& range = itemRanges.at(i);
+ const KItemRange& range = itemRanges[i];
const int index = range.index;
const int count = range.count;
if (index < 0 || count <= 0) {
const int firstRemovedIndex = index;
const int lastRemovedIndex = index + count - 1;
- const int lastIndex = m_model->count() + count - 1;
+ const int lastIndex = m_model->count() - 1 + removedItemsCount;
+ removedItemsCount -= count;
// Remove all KItemListWidget instances that got deleted
for (int i = firstRemovedIndex; i <= lastRemovedIndex; ++i) {
return m_itemSize.isEmpty() && m_visibleRoles.count() > 1;
}
+QHash<QByteArray, qreal> KItemListView::preferredColumnWidths(const KItemRangeList& itemRanges) const
+{
+ QElapsedTimer timer;
+ timer.start();
+
+ QHash<QByteArray, qreal> widths;
+
+ // Calculate the minimum width for each column that is required
+ // to show the headline unclipped.
+ const QFontMetricsF fontMetrics(m_headerWidget->font());
+ const int gripMargin = m_headerWidget->style()->pixelMetric(QStyle::PM_HeaderGripMargin);
+ const int headerMargin = m_headerWidget->style()->pixelMetric(QStyle::PM_HeaderMargin);
+ foreach (const QByteArray& visibleRole, visibleRoles()) {
+ const QString headerText = m_model->roleDescription(visibleRole);
+ const qreal headerWidth = fontMetrics.width(headerText) + gripMargin + headerMargin * 2;
+ widths.insert(visibleRole, headerWidth);
+ }
+
+ // Calculate the preferred column withs for each item and ignore values
+ // smaller than the width for showing the headline unclipped.
+ int calculatedItemCount = 0;
+ bool maxTimeExceeded = false;
+ foreach (const KItemRange& itemRange, itemRanges) {
+ const int startIndex = itemRange.index;
+ const int endIndex = startIndex + itemRange.count - 1;
+
+ for (int i = startIndex; i <= endIndex; ++i) {
+ foreach (const QByteArray& visibleRole, visibleRoles()) {
+ qreal maxWidth = widths.value(visibleRole, 0);
+ const qreal width = m_widgetCreator->preferredRoleColumnWidth(visibleRole, i, this);
+ maxWidth = qMax(width, maxWidth);
+ widths.insert(visibleRole, maxWidth);
+ }
+
+ if (calculatedItemCount > 100 && timer.elapsed() > 200) {
+ // When having several thousands of items calculating the sizes can get
+ // very expensive. We accept a possibly too small role-size in favour
+ // of having no blocking user interface.
+ maxTimeExceeded = true;
+ break;
+ }
+ ++calculatedItemCount;
+ }
+ if (maxTimeExceeded) {
+ break;
+ }
+ }
+
+ return widths;
+}
+
void KItemListView::applyColumnWidthsFromHeader()
{
// Apply the new size to the layouter
const QSizeF dynamicItemSize(qMax(size().width(), requiredWidth),
m_itemSize.height());
m_layouter->setItemSize(dynamicItemSize);
- m_headerWidget->resize(dynamicItemSize.width(), m_headerWidget->size().height());
// Update the role sizes for all visible widgets
QHashIterator<int, KItemListWidget*> it(m_visibleItems);
void KItemListView::updatePreferredColumnWidths()
{
- if (!m_model) {
- return;
- }
-
- const int itemCount = m_model->count();
- if (itemCount > 0) {
- updatePreferredColumnWidths(KItemRangeList() << KItemRange(0, itemCount));
+ if (m_model) {
+ updatePreferredColumnWidths(KItemRangeList() << KItemRange(0, m_model->count()));
}
}
dynamicItemSize.rwidth() = qMax(requiredWidth, availableWidth);
m_layouter->setItemSize(dynamicItemSize);
- m_headerWidget->resize(dynamicItemSize.width(), m_headerWidget->size().height());
// Update the role sizes for all visible widgets
QHashIterator<int, KItemListWidget*> it(m_visibleItems);