/**
* This file is part of the KDE project
- * Copyright (C) 2007 Rafael Fernández López <ereslibre@gmail.com>
+ * Copyright (C) 2007 Rafael Fernández López <ereslibre@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
}
}
+void KCategorizedView::Private::layoutChanged(bool forceItemReload)
+{
+ if ((listView->viewMode() == KCategorizedView::IconMode) && proxyModel &&
+ categoryDrawer && proxyModel->isCategorizedModel() &&
+ ((forceItemReload ||
+ (modelSortRole != proxyModel->sortRole()) ||
+ (modelSortColumn != proxyModel->sortColumn()) ||
+ (modelSortOrder != proxyModel->sortOrder()) ||
+ (modelLastRowCount != proxyModel->rowCount()) ||
+ (modelCategorized != proxyModel->isCategorizedModel()))))
+ {
+ // Force the view to update all elements
+ listView->rowsInsertedArtifficial(QModelIndex(), 0, proxyModel->rowCount() - 1);
+
+ if (!forceItemReload)
+ {
+ modelSortRole = proxyModel->sortRole();
+ modelSortColumn = proxyModel->sortColumn();
+ modelSortOrder = proxyModel->sortOrder();
+ modelLastRowCount = proxyModel->rowCount();
+ modelCategorized = proxyModel->isCategorizedModel();
+ }
+ }
+ else if ((listView->viewMode() == KCategorizedView::IconMode) && proxyModel &&
+ categoryDrawer && proxyModel->isCategorizedModel())
+ {
+ updateScrollbars();
+ }
+}
+
void KCategorizedView::Private::drawDraggedItems()
{
QRect rectToUpdate;
{
QListView::setGridSize(size);
- slotLayoutChanged();
+ d->layoutChanged(true);
}
void KCategorizedView::setModel(QAbstractItemModel *model)
QObject::disconnect(d->proxyModel,
SIGNAL(dataChanged(QModelIndex,QModelIndex)),
this, SLOT(slotLayoutChanged()));
+
+ QObject::disconnect(d->proxyModel,
+ SIGNAL(rowsRemoved(QModelIndex,int,int)),
+ this, SLOT(rowsRemoved(QModelIndex,int,int)));
}
QListView::setModel(model);
if (d->proxyModel)
{
+ d->modelSortRole = d->proxyModel->sortRole();
+ d->modelSortColumn = d->proxyModel->sortColumn();
+ d->modelSortOrder = d->proxyModel->sortOrder();
+ d->modelLastRowCount = d->proxyModel->rowCount();
+ d->modelCategorized = d->proxyModel->isCategorizedModel();
+
QObject::connect(d->proxyModel,
SIGNAL(layoutChanged()),
this, SLOT(slotLayoutChanged()));
QObject::connect(d->proxyModel,
SIGNAL(dataChanged(QModelIndex,QModelIndex)),
this, SLOT(slotLayoutChanged()));
+
+ QObject::connect(d->proxyModel,
+ SIGNAL(rowsRemoved(QModelIndex,int,int)),
+ this, SLOT(rowsRemoved(QModelIndex,int,int)));
+
+ if (d->proxyModel->rowCount())
+ {
+ d->layoutChanged(true);
+ }
+ }
+ else
+ {
+ d->modelCategorized = false;
}
}
QObject::disconnect(d->proxyModel,
SIGNAL(dataChanged(QModelIndex,QModelIndex)),
this, SLOT(slotLayoutChanged()));
+
+ QObject::disconnect(d->proxyModel,
+ SIGNAL(rowsRemoved(QModelIndex,int,int)),
+ this, SLOT(rowsRemoved(QModelIndex,int,int)));
}
else if (categoryDrawer && d->proxyModel)
{
QObject::connect(d->proxyModel,
SIGNAL(dataChanged(QModelIndex,QModelIndex)),
this, SLOT(slotLayoutChanged()));
+
+ QObject::connect(d->proxyModel,
+ SIGNAL(rowsRemoved(QModelIndex,int,int)),
+ this, SLOT(rowsRemoved(QModelIndex,int,int)));
}
d->categoryDrawer = categoryDrawer;
{
if (d->proxyModel)
{
- rowsInserted(QModelIndex(), 0, d->proxyModel->rowCount() - 1);
+ if (d->proxyModel->rowCount())
+ {
+ d->layoutChanged(true);
+ }
}
}
else
// Redraw categories
QStyleOptionViewItem otherOption;
+ bool intersectedInThePast = false;
foreach (const QString &category, d->categories)
{
otherOption = option;
if (otherOption.rect.intersects(area))
{
+ intersectedInThePast = true;
+
QModelIndex indexToDraw = d->proxyModel->index(d->categoriesIndexes[category][0].row(), d->proxyModel->sortColumn());
d->drawNewCategory(indexToDraw,
d->proxyModel->sortRole(), otherOption, &painter);
}
+ else if (intersectedInThePast)
+ {
+ break; // the visible area has been finished, we don't need to keep asking, the rest won't intersect
+ // this is doable because we know that categories are correctly ordered on the list
+ }
}
if (d->mouseButtonPressed && !d->isDragging)
void KCategorizedView::startDrag(Qt::DropActions supportedActions)
{
+ // FIXME: QAbstractItemView does far better here since it sets the
+ // pixmap of selected icons to the dragging cursor, but it sets a non
+ // ARGB window so it is no transparent. Use QAbstractItemView when
+ // this is fixed on Qt.
+ // QAbstractItemView::startDrag(supportedActions);
QListView::startDrag(supportedActions);
d->isDragging = false;
}
QModelIndex KCategorizedView::moveCursor(CursorAction cursorAction,
- Qt::KeyboardModifiers modifiers)
+ Qt::KeyboardModifiers modifiers)
{
if ((viewMode() != KCategorizedView::IconMode) ||
!d->proxyModel ||
break;
}
- if (category == d->elementsInfo[d->proxyModel->mapToSource(current).row()].category)
+ if (category == d->elementsInfo[current.row()].category)
{
theCategory = category;
lastCategory = category;
}
}
-// ### FIXME !!!
-#if 0
+
switch (cursorAction)
{
case QAbstractItemView::MoveUp: {
- if (d->elementsInfo[d->proxyModel->mapToSource(current).row()].relativeOffsetToCategory >= elementsPerRow)
+ if (d->elementsInfo[current.row()].relativeOffsetToCategory >= elementsPerRow)
{
- int indexToMove = d->invertedElementDictionary[current.row()].row();
- indexToMove -= qMin(((d->elementsInfo[d->proxyModel->mapToSource(current).row()].relativeOffsetToCategory) + d->forcedSelectionPosition), elementsPerRow - d->forcedSelectionPosition + (d->elementsInfo[d->proxyModel->mapToSource(current).row()].relativeOffsetToCategory % elementsPerRow));
+ int indexToMove = current.row();
+ indexToMove -= qMin(((d->elementsInfo[current.row()].relativeOffsetToCategory) + d->forcedSelectionPosition), elementsPerRow - d->forcedSelectionPosition + (d->elementsInfo[current.row()].relativeOffsetToCategory % elementsPerRow));
- return d->elementDictionary[indexToMove];
+ return d->proxyModel->index(indexToMove, 0);
}
else
{
int lastCategoryLastRow = (d->categoriesIndexes[lastCategory].count() - 1) % elementsPerRow;
- int indexToMove = d->invertedElementDictionary[current.row()].row() - d->elementsInfo[d->proxyModel->mapToSource(current).row()].relativeOffsetToCategory;
+ int indexToMove = current.row() - d->elementsInfo[current.row()].relativeOffsetToCategory;
if (d->forcedSelectionPosition >= lastCategoryLastRow)
{
indexToMove -= qMin((lastCategoryLastRow - d->forcedSelectionPosition + 1), d->forcedSelectionPosition + elementsPerRow + 1);
}
- return d->elementDictionary[indexToMove];
+ return d->proxyModel->index(indexToMove, 0);
}
}
case QAbstractItemView::MoveDown: {
- if (d->elementsInfo[d->proxyModel->mapToSource(current).row()].relativeOffsetToCategory < (d->categoriesIndexes[theCategory].count() - 1 - ((d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow)))
+ if (d->elementsInfo[current.row()].relativeOffsetToCategory < (d->categoriesIndexes[theCategory].count() - 1 - ((d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow)))
{
- int indexToMove = d->invertedElementDictionary[current.row()].row();
- indexToMove += qMin(elementsPerRow, d->categoriesIndexes[theCategory].count() - 1 - d->elementsInfo[d->proxyModel->mapToSource(current).row()].relativeOffsetToCategory);
+ int indexToMove = current.row();
+ indexToMove += qMin(elementsPerRow, d->categoriesIndexes[theCategory].count() - 1 - d->elementsInfo[current.row()].relativeOffsetToCategory);
- return d->elementDictionary[indexToMove];
+ return d->proxyModel->index(indexToMove, 0);
}
else
{
int afterCategoryLastRow = qMin(elementsPerRow, d->categoriesIndexes[afterCategory].count());
- int indexToMove = d->invertedElementDictionary[current.row()].row() + (d->categoriesIndexes[theCategory].count() - d->elementsInfo[d->proxyModel->mapToSource(current).row()].relativeOffsetToCategory);
+ int indexToMove = current.row() + (d->categoriesIndexes[theCategory].count() - d->elementsInfo[current.row()].relativeOffsetToCategory);
if (d->forcedSelectionPosition >= afterCategoryLastRow)
{
indexToMove += qMin(d->forcedSelectionPosition, elementsPerRow);
}
- return d->elementDictionary[indexToMove];
+ return d->proxyModel->index(indexToMove, 0);
}
}
case QAbstractItemView::MoveLeft:
- d->forcedSelectionPosition = d->elementsInfo[d->proxyModel->mapToSource(d->elementDictionary[d->proxyModel->index(d->invertedElementDictionary[current.row()].row() - 1, 0).row()]).row()].relativeOffsetToCategory % elementsPerRow;
+ if (layoutDirection() == Qt::RightToLeft)
+ {
+ d->forcedSelectionPosition = d->elementsInfo[current.row() + 1].relativeOffsetToCategory % elementsPerRow;
+
+ if (d->forcedSelectionPosition < 0)
+ d->forcedSelectionPosition = (d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow;
+
+ return d->proxyModel->index(current.row() + 1, 0);
+ }
+
+ d->forcedSelectionPosition = d->elementsInfo[current.row() - 1].relativeOffsetToCategory % elementsPerRow;
if (d->forcedSelectionPosition < 0)
d->forcedSelectionPosition = (d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow;
- return d->elementDictionary[d->proxyModel->index(d->invertedElementDictionary[current.row()].row() - 1, 0).row()];
+ return d->proxyModel->index(current.row() - 1, 0);
case QAbstractItemView::MoveRight:
- d->forcedSelectionPosition = d->elementsInfo[d->proxyModel->mapToSource(d->elementDictionary[d->proxyModel->index(d->invertedElementDictionary[current.row()].row() + 1, 0).row()]).row()].relativeOffsetToCategory % elementsPerRow;
+ if (layoutDirection() == Qt::RightToLeft)
+ {
+ d->forcedSelectionPosition = d->elementsInfo[current.row() - 1].relativeOffsetToCategory % elementsPerRow;
+
+ if (d->forcedSelectionPosition < 0)
+ d->forcedSelectionPosition = (d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow;
+
+ return d->proxyModel->index(current.row() - 1, 0);
+ }
+
+ d->forcedSelectionPosition = d->elementsInfo[current.row() + 1].relativeOffsetToCategory % elementsPerRow;
if (d->forcedSelectionPosition < 0)
d->forcedSelectionPosition = (d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow;
- return d->elementDictionary[d->proxyModel->index(d->invertedElementDictionary[current.row()].row() + 1, 0).row()];
+ return d->proxyModel->index(current.row() + 1, 0);
default:
break;
}
-#endif
+
return QListView::moveCursor(cursorAction, modifiers);
}
void KCategorizedView::rowsInserted(const QModelIndex &parent,
- int start,
- int end)
+ int start,
+ int end)
{
QListView::rowsInserted(parent, start, end);
}
void KCategorizedView::rowsInsertedArtifficial(const QModelIndex &parent,
- int start,
- int end)
+ int start,
+ int end)
{
Q_UNUSED(parent);
return;
}
- // Add all elements mapped to the source model
- for (int k = 0; k < d->proxyModel->rowCount(); k++)
- {
- d->biggestItemSize = QSize(qMax(sizeHintForIndex(d->proxyModel->index(k, 0)).width(),
- d->biggestItemSize.width()),
- qMax(sizeHintForIndex(d->proxyModel->index(k, 0)).height(),
- d->biggestItemSize.height()));
-
- d->modelIndexList << d->proxyModel->index(k, d->proxyModel->sortColumn());
- }
-
- // Explore categories
- QString prevCategory = d->proxyModel->data(d->modelIndexList[0], KCategorizedSortFilterProxyModel::CategoryRole).toString();
+ // Add all elements mapped to the source model and explore categories
+ QString prevCategory = d->proxyModel->data(d->proxyModel->index(0, d->proxyModel->sortColumn()), KCategorizedSortFilterProxyModel::CategoryRole).toString();
QString lastCategory = prevCategory;
QModelIndexList modelIndexList;
struct Private::ElementInfo elementInfo;
int offset = -1;
- foreach (const QModelIndex &index, d->modelIndexList)
+ for (int k = 0; k < d->proxyModel->rowCount(); ++k)
{
+ QModelIndex index = d->proxyModel->index(k, d->proxyModel->sortColumn());
+ QModelIndex indexSize = d->proxyModel->index(k, 0);
+
+ d->biggestItemSize = QSize(qMax(sizeHintForIndex(indexSize).width(),
+ d->biggestItemSize.width()),
+ qMax(sizeHintForIndex(indexSize).height(),
+ d->biggestItemSize.height()));
+
+ d->modelIndexList << index;
+
lastCategory = d->proxyModel->data(index, KCategorizedSortFilterProxyModel::CategoryRole).toString();
elementInfo.category = lastCategory;
}
void KCategorizedView::rowsRemoved(const QModelIndex &parent,
- int start,
- int end)
+ int start,
+ int end)
{
if ((viewMode() == KCategorizedView::IconMode) && d->proxyModel &&
d->categoryDrawer && d->proxyModel->isCategorizedModel())
{
// Force the view to update all elements
- rowsInsertedArtifficial(parent, start, end);
+ rowsInsertedArtifficial(QModelIndex(), 0, d->proxyModel->rowCount() - 1);
}
}
void KCategorizedView::slotLayoutChanged()
{
- if ((viewMode() == KCategorizedView::IconMode) && d->proxyModel &&
- d->categoryDrawer && d->proxyModel->isCategorizedModel())
- {
- // Force the view to update all elements
- rowsInsertedArtifficial(QModelIndex(), 0, d->proxyModel->rowCount() - 1);
- }
+ d->layoutChanged();
}
#include "kcategorizedview.moc"