#include "kcategorydrawer.h"
#include "kcategorizedsortfilterproxymodel.h"
+// By defining DOLPHIN_DRAGANDDROP the custom drag and drop implementation of
+// KCategorizedView is bypassed to have a consistent drag and drop look for all
+// views. Hopefully transparent pixmaps for drag objects will be supported in
+// Qt 4.4, so that this workaround can be skipped.
+#define DOLPHIN_DRAGANDDROP
+
KCategorizedView::Private::Private(KCategorizedView *listView)
: listView(listView)
, categoryDrawer(0)
int lastItemBottom = cachedRectIndex(lastIndex).top() +
listView->spacing() + (listView->gridSize().isEmpty() ? 0 : listView->gridSize().height()) - listView->viewport()->height();
+ listView->horizontalScrollBar()->setRange(0, 0);
+
listView->verticalScrollBar()->setSingleStep(listView->viewport()->height() / 10);
listView->verticalScrollBar()->setPageStep(listView->viewport()->height());
listView->verticalScrollBar()->setRange(0, lastItemBottom);
}
}
+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)
// 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.
- //QListView::startDrag(supportedActions);
- QAbstractItemView::startDrag(supportedActions);
+ // QAbstractItemView::startDrag(supportedActions);
+#if !defined(DOLPHIN_DRAGANDDROP)
+ QListView::startDrag(supportedActions);
+#endif
d->isDragging = false;
d->mouseButtonPressed = false;
if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
!d->categoryDrawer || !d->proxyModel->isCategorizedModel())
{
+#if defined(DOLPHIN_DRAGANDDROP)
+ QAbstractItemView::dragMoveEvent(event);
+#else
QListView::dragMoveEvent(event);
+#endif
return;
}
{
d->dragLeftViewport = true;
+#if defined(DOLPHIN_DRAGANDDROP)
+ QAbstractItemView::dragLeaveEvent(event);
+#else
QListView::dragLeaveEvent(event);
+#endif
+}
+
+void KCategorizedView::dropEvent(QDropEvent *event)
+{
+#if defined(DOLPHIN_DRAGANDDROP)
+ QAbstractItemView::dropEvent(event);
+#else
+ QListView::dropEvent(event);
+#endif
}
QModelIndex KCategorizedView::moveCursor(CursorAction cursorAction,
- Qt::KeyboardModifiers modifiers)
+ Qt::KeyboardModifiers modifiers)
{
if ((viewMode() != KCategorizedView::IconMode) ||
!d->proxyModel ||
}
case QAbstractItemView::MoveLeft:
+ 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)
return d->proxyModel->index(current.row() - 1, 0);
case QAbstractItemView::MoveRight:
+ 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)
}
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"