/**
* 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
#include <math.h> // trunc on C99 compliant systems
#include <kdefakes.h> // trunc for not C99 compliant systems
-#include <QApplication>
#include <QPainter>
#include <QScrollBar>
#include <QPaintEvent>
-#include <kdebug.h>
#include <kstyle.h>
-#include "kitemcategorizer.h"
-#include "ksortfilterproxymodel.h"
-
-class LessThan
-{
-public:
- enum Purpose
- {
- GeneralPurpose = 0,
- CategoryPurpose
- };
-
- inline LessThan(const KSortFilterProxyModel *proxyModel,
- Purpose purpose)
- : proxyModel(proxyModel)
- , purpose(purpose)
- {
- }
-
- inline bool operator()(const QModelIndex &left,
- const QModelIndex &right) const
- {
- if (purpose == GeneralPurpose)
- {
- return proxyModel->sortOrder() == Qt::AscendingOrder ?
- proxyModel->lessThanGeneralPurpose(left, right) :
- !proxyModel->lessThanGeneralPurpose(left, right);
- }
-
- return proxyModel->sortOrder() == Qt::AscendingOrder ?
- proxyModel->lessThanCategoryPurpose(left, right) :
- !proxyModel->lessThanCategoryPurpose(left, right);
- }
-
-private:
- const KSortFilterProxyModel *proxyModel;
- const Purpose purpose;
-};
-
-
-//==============================================================================
+#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)
- , itemCategorizer(0)
+ , categoryDrawer(0)
, biggestItemSize(QSize(0, 0))
, mouseButtonPressed(false)
+ , rightMouseButtonPressed(false)
, isDragging(false)
, dragLeftViewport(false)
, proxyModel(0)
- , lastIndex(QModelIndex())
{
}
{
middle = (top + bottom) / 2;
- index = elementDictionary[proxyModel->index(middle, 0)];
+ index = proxyModel->index(middle, 0);
indexVisualRect = visualRect(index);
// We need the whole height (not only the visualRect). This will help us to update
// all needed indexes correctly (ereslibre)
for (int i = middle; i < proxyModel->rowCount(); i++)
{
- index = elementDictionary[proxyModel->index(i, 0)];
+ index = proxyModel->index(i, 0);
indexVisualRect = visualRect(index);
if (rect.intersects(indexVisualRect))
if (!index.isValid())
return QRect();
- QString curCategory = elementsInfo[index].category;
+ QString curCategory = elementsInfo[index.row()].category;
- QRect retRect(listView->spacing(), listView->spacing() * 2 +
- itemCategorizer->categoryHeight(listView->viewOptions()), 0, 0);
+ QRect retRect;
+
+ if (listView->layoutDirection() == Qt::LeftToRight)
+ {
+ retRect = QRect(listView->spacing(), listView->spacing() * 2 +
+ categoryDrawer->categoryHeight(index, listView->viewOptions()), 0, 0);
+ }
+ else
+ {
+ retRect = QRect(listView->viewport()->width() - listView->spacing(), listView->spacing() * 2 +
+ categoryDrawer->categoryHeight(index, listView->viewOptions()), 0, 0);
+ }
int viewportWidth = listView->viewport()->width() - listView->spacing();
if (!elementsPerRow)
elementsPerRow++;
- int column = elementsInfo[index].relativeOffsetToCategory % elementsPerRow;
- int row = elementsInfo[index].relativeOffsetToCategory / elementsPerRow;
+ int column = elementsInfo[index.row()].relativeOffsetToCategory % elementsPerRow;
+ int row = elementsInfo[index.row()].relativeOffsetToCategory / elementsPerRow;
+
+ if (listView->layoutDirection() == Qt::LeftToRight)
+ {
+ retRect.setLeft(retRect.left() + column * listView->spacing() +
+ column * itemWidth);
+ }
+ else
+ {
+ retRect.setLeft(retRect.right() - column * listView->spacing() -
+ column * itemWidth - itemWidth);
- retRect.setLeft(retRect.left() + column * listView->spacing() +
- column * itemWidth);
+ retRect.setRight(retRect.right() - column * listView->spacing() -
+ column * itemWidth);
+ }
foreach (const QString &category, categories)
{
float rows = (float) ((float) categoriesIndexes[category].count() /
(float) elementsPerRow);
+
int rowsInt = categoriesIndexes[category].count() / elementsPerRow;
if (rows - trunc(rows)) rowsInt++;
retRect.setTop(retRect.top() +
(rowsInt * itemHeight) +
- itemCategorizer->categoryHeight(listView->viewOptions()) +
+ categoryDrawer->categoryHeight(index, listView->viewOptions()) +
listView->spacing() * 2);
if (listView->gridSize().isEmpty())
}
}
-
if (listView->gridSize().isEmpty())
{
retRect.setTop(retRect.top() + row * listView->spacing() +
retRect.setWidth(itemWidth);
+ QModelIndex heightIndex = proxyModel->index(index.row(), 0);
if (listView->gridSize().isEmpty())
{
- retRect.setHeight(listView->sizeHintForIndex(proxyModel->mapFromSource(index)).height());
+ retRect.setHeight(listView->sizeHintForIndex(heightIndex).height());
}
else
{
- retRect.setHeight(qMin(listView->sizeHintForIndex(proxyModel->mapFromSource(index)).height(),
+ retRect.setHeight(qMin(listView->sizeHintForIndex(heightIndex).height(),
listView->gridSize().height()));
}
retRect.setTop(retRect.top() +
(rowsInt * itemHeight) +
- itemCategorizer->categoryHeight(listView->viewOptions()) +
+ categoryDrawer->categoryHeight(index, listView->viewOptions()) +
listView->spacing() * 2);
if (listView->gridSize().isEmpty())
}
}
- retRect.setHeight(itemCategorizer->categoryHeight(listView->viewOptions()));
+ retRect.setHeight(categoryDrawer->categoryHeight(index, listView->viewOptions()));
return retRect;
}
const QRect &KCategorizedView::Private::cacheIndex(const QModelIndex &index)
{
QRect rect = visualRectInViewport(index);
- elementsPosition[index] = rect;
+ elementsPosition[index.row()] = rect;
- return elementsPosition[index];
+ return elementsPosition[index.row()];
}
// We're sure categoriesPosition doesn't contain category
const QRect &KCategorizedView::Private::cachedRectIndex(const QModelIndex &index)
{
- if (elementsPosition.contains(index)) // If we have it cached
+ if (elementsPosition.contains(index.row())) // If we have it cached
{ // return it
- return elementsPosition[index];
+ return elementsPosition[index.row()];
}
else // Otherwise, cache it
{ // and return it
QRect KCategorizedView::Private::visualRect(const QModelIndex &index)
{
- QModelIndex mappedIndex = proxyModel->mapToSource(index);
-
- QRect retRect = cachedRectIndex(mappedIndex);
+ QRect retRect = cachedRectIndex(index);
int dx = -listView->horizontalOffset();
int dy = -listView->verticalOffset();
retRect.adjust(dx, dy, dx, dy);
}
void KCategorizedView::Private::drawNewCategory(const QModelIndex &index,
- int sortRole,
- const QStyleOption &option,
- QPainter *painter)
+ int sortRole,
+ const QStyleOption &option,
+ QPainter *painter)
{
+ if (!index.isValid())
+ {
+ return;
+ }
+
QStyleOption optionCopy = option;
- const QString category = itemCategorizer->categoryForItem(index, sortRole);
+ const QString category = proxyModel->data(index, KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString();
- if ((category == hoveredCategory) && !mouseButtonPressed)
- {
- optionCopy.state |= QStyle::State_MouseOver;
+ optionCopy.state &= ~QStyle::State_Selected;
+
+ if ((listView->selectionMode() != SingleSelection) && (listView->selectionMode() != NoSelection)) {
+ if ((category == hoveredCategory) && !mouseButtonPressed)
+ {
+ optionCopy.state |= QStyle::State_MouseOver;
+ }
+ else if ((category == hoveredCategory) && mouseButtonPressed)
+ {
+ QPoint initialPressPosition = listView->viewport()->mapFromGlobal(QCursor::pos());
+ initialPressPosition.setY(initialPressPosition.y() + listView->verticalOffset());
+ initialPressPosition.setX(initialPressPosition.x() + listView->horizontalOffset());
+
+ if (initialPressPosition == this->initialPressPosition)
+ {
+ optionCopy.state |= QStyle::State_Selected;
+ }
+ }
}
- itemCategorizer->drawCategory(index,
- sortRole,
- optionCopy,
- painter);
+ categoryDrawer->drawCategory(index,
+ sortRole,
+ optionCopy,
+ painter);
}
void KCategorizedView::Private::updateScrollbars()
{
+ // find the last index in the last category
+ QModelIndex lastIndex = categoriesIndexes.isEmpty() ? QModelIndex() : categoriesIndexes[categories.last()].last();
+
int lastItemBottom = cachedRectIndex(lastIndex).top() +
- listView->spacing() + (listView->gridSize().isEmpty() ? 0 : listView->gridSize().height()) - listView->viewport()->height();
+ listView->spacing() + (listView->gridSize().isEmpty() ? biggestItemSize.height() : listView->gridSize().height()) - listView->viewport()->height();
+
+ listView->horizontalScrollBar()->setRange(0, 0);
listView->verticalScrollBar()->setSingleStep(listView->viewport()->height() / 10);
listView->verticalScrollBar()->setPageStep(listView->viewport()->height());
}
}
+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;
delete d;
}
+void KCategorizedView::setGridSize(const QSize &size)
+{
+ QListView::setGridSize(size);
+
+ d->layoutChanged(true);
+}
+
void KCategorizedView::setModel(QAbstractItemModel *model)
{
d->lastSelection = QItemSelection();
- d->currentViewIndex = QModelIndex();
d->forcedSelectionPosition = 0;
d->elementsInfo.clear();
d->elementsPosition.clear();
- d->elementDictionary.clear();
- d->invertedElementDictionary.clear();
d->categoriesIndexes.clear();
d->categoriesPosition.clear();
d->categories.clear();
d->intersectedIndexes.clear();
- d->sourceModelIndexList.clear();
+ d->modelIndexList.clear();
d->hovered = QModelIndex();
d->mouseButtonPressed = false;
+ d->rightMouseButtonPressed = false;
if (d->proxyModel)
{
QObject::disconnect(d->proxyModel,
- SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(rowsRemoved(QModelIndex,int,int)));
+ SIGNAL(layoutChanged()),
+ this, SLOT(slotLayoutChanged()));
QObject::disconnect(d->proxyModel,
- SIGNAL(sortingRoleChanged()),
- this, SLOT(slotSortingRoleChanged()));
+ 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);
- d->proxyModel = dynamic_cast<KSortFilterProxyModel*>(model);
+ d->proxyModel = dynamic_cast<KCategorizedSortFilterProxyModel*>(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)));
- QObject::connect(d->proxyModel,
- SIGNAL(sortingRoleChanged()),
- this, SLOT(slotSortingRoleChanged()));
+ if (d->proxyModel->rowCount())
+ {
+ d->layoutChanged(true);
+ }
+ }
+ else
+ {
+ d->modelCategorized = false;
}
}
QRect KCategorizedView::visualRect(const QModelIndex &index) const
{
if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->itemCategorizer)
+ !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
{
return QListView::visualRect(index);
}
return d->visualRect(index);
}
-KItemCategorizer *KCategorizedView::itemCategorizer() const
+KCategoryDrawer *KCategorizedView::categoryDrawer() const
{
- return d->itemCategorizer;
+ return d->categoryDrawer;
}
-void KCategorizedView::setItemCategorizer(KItemCategorizer *itemCategorizer)
+void KCategorizedView::setCategoryDrawer(KCategoryDrawer *categoryDrawer)
{
d->lastSelection = QItemSelection();
- d->currentViewIndex = QModelIndex();
d->forcedSelectionPosition = 0;
d->elementsInfo.clear();
d->elementsPosition.clear();
- d->elementDictionary.clear();
- d->invertedElementDictionary.clear();
d->categoriesIndexes.clear();
d->categoriesPosition.clear();
d->categories.clear();
d->intersectedIndexes.clear();
- d->sourceModelIndexList.clear();
+ d->modelIndexList.clear();
d->hovered = QModelIndex();
d->mouseButtonPressed = false;
+ d->rightMouseButtonPressed = false;
- if (!itemCategorizer && d->proxyModel)
+ if (!categoryDrawer && d->proxyModel)
{
QObject::disconnect(d->proxyModel,
- SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(rowsRemoved(QModelIndex,int,int)));
+ SIGNAL(layoutChanged()),
+ this, SLOT(slotLayoutChanged()));
+
+ QObject::disconnect(d->proxyModel,
+ SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ this, SLOT(slotLayoutChanged()));
QObject::disconnect(d->proxyModel,
- SIGNAL(sortingRoleChanged()),
- this, SLOT(slotSortingRoleChanged()));
+ SIGNAL(rowsRemoved(QModelIndex,int,int)),
+ this, SLOT(rowsRemoved(QModelIndex,int,int)));
}
- else if (itemCategorizer && d->proxyModel)
+ else if (categoryDrawer && d->proxyModel)
{
QObject::connect(d->proxyModel,
- SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(rowsRemoved(QModelIndex,int,int)));
+ SIGNAL(layoutChanged()),
+ this, SLOT(slotLayoutChanged()));
+
+ QObject::connect(d->proxyModel,
+ SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ this, SLOT(slotLayoutChanged()));
QObject::connect(d->proxyModel,
- SIGNAL(sortingRoleChanged()),
- this, SLOT(slotSortingRoleChanged()));
+ SIGNAL(rowsRemoved(QModelIndex,int,int)),
+ this, SLOT(rowsRemoved(QModelIndex,int,int)));
}
- d->itemCategorizer = itemCategorizer;
+ d->categoryDrawer = categoryDrawer;
- if (itemCategorizer)
+ if (categoryDrawer)
{
- rowsInserted(QModelIndex(), 0, d->proxyModel->rowCount() - 1);
+ if (d->proxyModel)
+ {
+ if (d->proxyModel->rowCount())
+ {
+ d->layoutChanged(true);
+ }
+ }
}
else
{
QModelIndex KCategorizedView::indexAt(const QPoint &point) const
{
if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->itemCategorizer)
+ !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
{
return QListView::indexAt(point);
}
index = item[0];
}
- d->hovered = index;
-
return index;
}
QListView::reset();
d->lastSelection = QItemSelection();
- d->currentViewIndex = QModelIndex();
d->forcedSelectionPosition = 0;
d->elementsInfo.clear();
d->elementsPosition.clear();
- d->elementDictionary.clear();
- d->invertedElementDictionary.clear();
d->categoriesIndexes.clear();
d->categoriesPosition.clear();
d->categories.clear();
d->intersectedIndexes.clear();
- d->sourceModelIndexList.clear();
+ d->modelIndexList.clear();
d->hovered = QModelIndex();
d->biggestItemSize = QSize(0, 0);
d->mouseButtonPressed = false;
+ d->rightMouseButtonPressed = false;
}
void KCategorizedView::paintEvent(QPaintEvent *event)
{
if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->itemCategorizer)
+ !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
{
QListView::paintEvent(event);
return;
option.state |= QStyle::State_Editing;
}
- if ((index == d->hovered) && !d->mouseButtonPressed)
+ // we are only interested to give the mouse over feedback when no
+ // dragging is happening (ereslibre)
+ if ((index == d->hovered) && !d->mouseButtonPressed &&
+ (this->state() == QAbstractItemView::NoState))
option.state |= QStyle::State_MouseOver;
else
option.state &= ~QStyle::State_MouseOver;
// Redraw categories
QStyleOptionViewItem otherOption;
+ bool intersectedInThePast = false;
foreach (const QString &category, d->categories)
{
otherOption = option;
if (otherOption.rect.intersects(area))
{
- d->drawNewCategory(d->categoriesIndexes[category][0],
+ 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)
+ if ((selectionMode() != SingleSelection) && (selectionMode() != NoSelection))
{
- QPoint start, end, initialPressPosition;
+ if (d->mouseButtonPressed && !d->isDragging)
+ {
+ QPoint start, end, initialPressPosition;
- initialPressPosition = d->initialPressPosition;
+ initialPressPosition = d->initialPressPosition;
- initialPressPosition.setY(initialPressPosition.y() - verticalOffset());
- initialPressPosition.setX(initialPressPosition.x() - horizontalOffset());
+ initialPressPosition.setY(initialPressPosition.y() - verticalOffset());
+ initialPressPosition.setX(initialPressPosition.x() - horizontalOffset());
- if (d->initialPressPosition.x() > d->mousePosition.x() ||
- d->initialPressPosition.y() > d->mousePosition.y())
- {
- start = d->mousePosition;
- end = initialPressPosition;
- }
- else
- {
- start = initialPressPosition;
- end = d->mousePosition;
- }
+ if (d->initialPressPosition.x() > d->mousePosition.x() ||
+ d->initialPressPosition.y() > d->mousePosition.y())
+ {
+ start = d->mousePosition;
+ end = initialPressPosition;
+ }
+ else
+ {
+ start = initialPressPosition;
+ end = d->mousePosition;
+ }
- QStyleOptionRubberBand yetAnotherOption;
- yetAnotherOption.initFrom(this);
- yetAnotherOption.shape = QRubberBand::Rectangle;
- yetAnotherOption.opaque = false;
- yetAnotherOption.rect = QRect(start, end).intersected(viewport()->rect().adjusted(-16, -16, 16, 16));
- painter.save();
- style()->drawControl(QStyle::CE_RubberBand, &yetAnotherOption, &painter);
- painter.restore();
+ QStyleOptionRubberBand yetAnotherOption;
+ yetAnotherOption.initFrom(this);
+ yetAnotherOption.shape = QRubberBand::Rectangle;
+ yetAnotherOption.opaque = false;
+ yetAnotherOption.rect = QRect(start, end).intersected(viewport()->rect().adjusted(-16, -16, 16, 16));
+ painter.save();
+ style()->drawControl(QStyle::CE_RubberBand, &yetAnotherOption, &painter);
+ painter.restore();
+ }
}
if (d->isDragging && !d->dragLeftViewport)
d->forcedSelectionPosition = 0;
if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->itemCategorizer)
+ !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
{
return;
}
QItemSelectionModel::SelectionFlags flags)
{
if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->itemCategorizer)
+ !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
{
QListView::setSelection(rect, flags);
return;
if (!flags)
return;
- selectionModel()->clear();
-
if (flags & QItemSelectionModel::Clear)
{
- d->lastSelection = QItemSelection();
+ selectionModel()->clear();
+ d->lastSelection.clear();
}
QModelIndexList dirtyIndexes = d->intersectionSet(rect);
- QItemSelection selection;
-
+ // no items affected, just leave
if (!dirtyIndexes.count())
{
- if (d->lastSelection.count())
- {
- selectionModel()->select(d->lastSelection, flags);
- }
+ selectionModel()->select(d->lastSelection, QItemSelectionModel::SelectCurrent);
return;
}
- if (!d->mouseButtonPressed)
- {
- selection = QItemSelection(dirtyIndexes[0], dirtyIndexes[0]);
- d->currentViewIndex = dirtyIndexes[0];
- }
- else
+ QModelIndex topLeft;
+ QModelIndex bottomRight;
+
+ if (d->mouseButtonPressed || d->rightMouseButtonPressed) // selection with click + drag
{
- QModelIndex first = dirtyIndexes[0];
- QModelIndex last;
+ QItemSelection selection;
+
+ QModelIndex prev = dirtyIndexes[0];
+ QModelIndex first = prev;
foreach (const QModelIndex &index, dirtyIndexes)
{
- if (last.isValid() && last.row() + 1 != index.row())
- {
- QItemSelectionRange range(first, last);
-
- selection << range;
+ // we have a different interval. non-contiguous items
+ if ((index.row() - prev.row()) > 1) {
+ selection << QItemSelectionRange(first, prev);
first = index;
}
- last = index;
+ prev = index;
}
- if (last.isValid())
- selection << QItemSelectionRange(first, last);
- }
+ selection << QItemSelectionRange(first, prev);
- if (d->lastSelection.count() && !d->mouseButtonPressed)
- {
- selection.merge(d->lastSelection, flags);
+ if (flags & QItemSelectionModel::Current)
+ {
+ if (rect.topLeft() == rect.bottomRight())
+ {
+ selectionModel()->setCurrentIndex(indexAt(rect.topLeft()), QItemSelectionModel::NoUpdate);
+ }
+
+ selection.merge(d->lastSelection, flags);
+ }
+ else
+ {
+ selection.merge(selectionModel()->selection(), flags);
+
+ selectionModel()->select(selection, QItemSelectionModel::SelectCurrent);
+
+ return;
+ }
+
+ selectionModel()->select(selection, flags);
}
- else if (d->lastSelection.count())
+ else // selection with click + keyboard keys
{
- selection.merge(d->lastSelection, QItemSelectionModel::Select);
- }
+ QModelIndex topLeftIndex = indexAt(QPoint(rect.topLeft().x(),
+ rect.topLeft().y()));
+ QModelIndex bottomRightIndex = indexAt(QPoint(rect.bottomRight().x(),
+ rect.bottomRight().y()));
+
+ // keyboard selection comes "upside down". Let's normalize it
+ if (topLeftIndex.row() > bottomRightIndex.row())
+ {
+ QModelIndex auxIndex = topLeftIndex;
+ topLeftIndex = bottomRightIndex;
+ bottomRightIndex = auxIndex;
+ }
- selectionModel()->select(selection, flags);
+ int viewportWidth = viewport()->width() - spacing();
+ int itemWidth;
+
+ if (gridSize().isEmpty())
+ {
+ itemWidth = d->biggestItemSize.width();
+ }
+ else
+ {
+ itemWidth = gridSize().width();
+ }
+
+ int itemWidthPlusSeparation = spacing() + itemWidth;
+ int elementsPerRow = viewportWidth / itemWidthPlusSeparation;
+ if (!elementsPerRow)
+ elementsPerRow++;
+
+ QModelIndexList theoricDirty(dirtyIndexes);
+ dirtyIndexes.clear();
+ int first = model()->rowCount();
+ int last = 0;
+
+ foreach (const QModelIndex &index, theoricDirty)
+ {
+ if ((index.row() < first) &&
+ ((((topLeftIndex.row() / elementsPerRow) == (index.row() / elementsPerRow)) &&
+ ((topLeftIndex.row() % elementsPerRow) <= (index.row() % elementsPerRow))) ||
+ (topLeftIndex.row() / elementsPerRow) != (index.row() / elementsPerRow)))
+ {
+ first = index.row();
+ topLeft = index;
+ }
+
+ if ((index.row() > last) &&
+ ((((bottomRightIndex.row() / elementsPerRow) == (index.row() / elementsPerRow)) &&
+ ((bottomRightIndex.row() % elementsPerRow) >= (index.row() % elementsPerRow))) ||
+ (bottomRightIndex.row() / elementsPerRow) != (index.row() / elementsPerRow)))
+ {
+ last = index.row();
+ bottomRight = index;
+ }
+ }
+
+ for (int i = first; i <= last; i++)
+ {
+ dirtyIndexes << model()->index(i, theoricDirty[0].column(), theoricDirty[0].parent());
+ }
+
+ QItemSelection selection(topLeft, bottomRight);
+
+ selectionModel()->select(selection, flags);
+ }
}
void KCategorizedView::mouseMoveEvent(QMouseEvent *event)
QListView::mouseMoveEvent(event);
if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->itemCategorizer)
+ !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
{
return;
}
+ QModelIndexList item = d->intersectionSet(QRect(event->pos(), event->pos()));
+
+ if (item.count() == 1)
+ {
+ d->hovered = item[0];
+ }
+ else
+ {
+ d->hovered = QModelIndex();
+ }
+
const QString previousHoveredCategory = d->hoveredCategory;
d->mousePosition = event->pos();
end = d->mousePosition;
}
- rect = QRect(start, end).intersected(viewport()->rect().adjusted(-16, -16, 16, 16));
-
- //viewport()->update(rect.united(d->lastSelectionRect));
+ rect = QRect(start, end).adjusted(-16, -16, 16, 16);
+ rect = rect.united(QRect(start, end).adjusted(16, 16, -16, -16)).intersected(viewport()->rect());
- d->lastSelectionRect = rect;
+ viewport()->update(rect);
}
}
d->initialPressPosition.setX(d->initialPressPosition.x() +
horizontalOffset());
}
+ else if (event->button() == Qt::RightButton)
+ {
+ d->rightMouseButtonPressed = true;
+ }
QListView::mousePressEvent(event);
+
+ d->lastSelection = selectionModel()->selection();
+
+ viewport()->update(d->categoryVisualRect(d->hoveredCategory));
}
void KCategorizedView::mouseReleaseEvent(QMouseEvent *event)
{
d->mouseButtonPressed = false;
+ d->rightMouseButtonPressed = false;
QListView::mouseReleaseEvent(event);
if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->itemCategorizer)
+ !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
{
return;
}
initialPressPosition.setY(initialPressPosition.y() + verticalOffset());
initialPressPosition.setX(initialPressPosition.x() + horizontalOffset());
- QItemSelection selection;
-
- if (initialPressPosition == d->initialPressPosition)
+ if ((selectionMode() != SingleSelection) && (selectionMode() != NoSelection) &&
+ (initialPressPosition == d->initialPressPosition))
{
foreach(const QString &category, d->categories)
{
if (d->categoryVisualRect(category).contains(event->pos()))
{
- foreach (const QModelIndex &index, d->categoriesIndexes[category])
+ QItemSelection selection = selectionModel()->selection();
+ QModelIndexList indexList = d->categoriesIndexes[category];
+
+ foreach (const QModelIndex &index, indexList)
{
- selection << QItemSelectionRange(d->proxyModel->mapFromSource(index));
+ QModelIndex selectIndex = index.model()->index(index.row(), 0);
+
+ selection << QItemSelectionRange(selectIndex);
}
- selectionModel()->select(selection, QItemSelectionModel::Select);
+ selectionModel()->select(selection, QItemSelectionModel::SelectCurrent);
break;
}
}
}
- d->lastSelection = selectionModel()->selection();
+ QRect rect;
+ if (!d->isDragging)
+ {
+ QPoint start, end, initialPressPosition;
+
+ initialPressPosition = d->initialPressPosition;
+
+ initialPressPosition.setY(initialPressPosition.y() - verticalOffset());
+ initialPressPosition.setX(initialPressPosition.x() - horizontalOffset());
+
+ if (d->initialPressPosition.x() > d->mousePosition.x() ||
+ d->initialPressPosition.y() > d->mousePosition.y())
+ {
+ start = d->mousePosition;
+ end = initialPressPosition;
+ }
+ else
+ {
+ start = initialPressPosition;
+ end = d->mousePosition;
+ }
+
+ rect = QRect(start, end).adjusted(-16, -16, 16, 16);
+ rect = rect.united(QRect(start, end).adjusted(16, 16, -16, -16)).intersected(viewport()->rect());
+
+ viewport()->update(rect);
+ }
if (d->hovered.isValid())
viewport()->update(visualRect(d->hovered));
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);
+#if !defined(DOLPHIN_DRAGANDDROP)
QListView::startDrag(supportedActions);
+#endif
d->isDragging = false;
d->mouseButtonPressed = false;
+ d->rightMouseButtonPressed = false;
viewport()->update(d->lastDraggedItemsRect);
}
d->dragLeftViewport = false;
+#if defined(DOLPHIN_DRAGANDDROP)
+ QAbstractItemView::dragMoveEvent(event);
+#else
+ QListView::dragMoveEvent(event);
+#endif
+
if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->itemCategorizer)
+ !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
{
- QListView::dragMoveEvent(event);
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 ||
- !d->itemCategorizer)
+ if ((viewMode() != KCategorizedView::IconMode) ||
+ !d->proxyModel ||
+ !d->categoryDrawer ||
+ d->categories.isEmpty() ||
+ !d->proxyModel->isCategorizedModel()
+ )
{
return QListView::moveCursor(cursorAction, modifiers);
}
- const QModelIndex current = selectionModel()->currentIndex();
-
int viewportWidth = viewport()->width() - spacing();
int itemWidth;
int itemWidthPlusSeparation = spacing() + itemWidth;
int elementsPerRow = viewportWidth / itemWidthPlusSeparation;
+ if (!elementsPerRow)
+ elementsPerRow++;
+
+ QModelIndex current = selectionModel()->currentIndex();
+
+ if (!current.isValid())
+ {
+ if (cursorAction == MoveEnd)
+ {
+ current = model()->index(model()->rowCount() - 1, 0, QModelIndex());
+ d->forcedSelectionPosition = d->elementsInfo[current.row()].relativeOffsetToCategory % elementsPerRow;
+ }
+ else
+ {
+ current = model()->index(0, 0, QModelIndex());
+ d->forcedSelectionPosition = 0;
+ }
+
+ return current;
+ }
+ else if (!current.isValid())
+ {
+ return QModelIndex();
+ }
+
+ QString lastCategory = d->categories.first();
+ QString theCategory = d->categories.first();
+ QString afterCategory = d->categories.first();
- QString lastCategory = d->categories[0];
- QString theCategory = d->categories[0];
- QString afterCategory = d->categories[0];
bool hasToBreak = false;
foreach (const QString &category, d->categories)
{
break;
}
- if (category == d->elementsInfo[d->proxyModel->mapToSource(current)].category)
+ if (category == d->elementsInfo[current.row()].category)
{
theCategory = category;
switch (cursorAction)
{
case QAbstractItemView::MoveUp: {
- if (d->elementsInfo[d->proxyModel->mapToSource(current)].relativeOffsetToCategory >= elementsPerRow)
+ if (d->elementsInfo[current.row()].relativeOffsetToCategory >= elementsPerRow)
{
- int indexToMove = d->invertedElementDictionary[current].row();
- indexToMove -= qMin(((d->elementsInfo[d->proxyModel->mapToSource(current)].relativeOffsetToCategory) + d->forcedSelectionPosition), elementsPerRow - d->forcedSelectionPosition + (d->elementsInfo[d->proxyModel->mapToSource(current)].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[d->proxyModel->index(indexToMove, 0)];
+ return d->proxyModel->index(indexToMove, 0);
}
else
{
int lastCategoryLastRow = (d->categoriesIndexes[lastCategory].count() - 1) % elementsPerRow;
- int indexToMove = d->invertedElementDictionary[current].row() - d->elementsInfo[d->proxyModel->mapToSource(current)].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[d->proxyModel->index(indexToMove, 0)];
+ return d->proxyModel->index(indexToMove, 0);
}
}
case QAbstractItemView::MoveDown: {
- if (d->elementsInfo[d->proxyModel->mapToSource(current)].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();
- indexToMove += qMin(elementsPerRow, d->categoriesIndexes[theCategory].count() - 1 - d->elementsInfo[d->proxyModel->mapToSource(current)].relativeOffsetToCategory);
+ int indexToMove = current.row();
+ indexToMove += qMin(elementsPerRow, d->categoriesIndexes[theCategory].count() - 1 - d->elementsInfo[current.row()].relativeOffsetToCategory);
- return d->elementDictionary[d->proxyModel->index(indexToMove, 0)];
+ return d->proxyModel->index(indexToMove, 0);
}
else
{
int afterCategoryLastRow = qMin(elementsPerRow, d->categoriesIndexes[afterCategory].count());
- int indexToMove = d->invertedElementDictionary[current].row() + (d->categoriesIndexes[theCategory].count() - d->elementsInfo[d->proxyModel->mapToSource(current)].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[d->proxyModel->index(indexToMove, 0)];
+ 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() - 1, 0)])].relativeOffsetToCategory % elementsPerRow;
+ if (layoutDirection() == Qt::RightToLeft)
+ {
+ if (!(d->elementsInfo[current.row() + 1].relativeOffsetToCategory % elementsPerRow))
+ return current;
+
+ d->forcedSelectionPosition = d->elementsInfo[current.row() + 1].relativeOffsetToCategory % elementsPerRow;
+
+#if 0 //follow qt view behavior. lateral movements won't change visual row
+ if (d->forcedSelectionPosition < 0)
+ d->forcedSelectionPosition = (d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow;
+#endif
+
+ return d->proxyModel->index(current.row() + 1, 0);
+ }
+
+ if (!(d->elementsInfo[current.row()].relativeOffsetToCategory % elementsPerRow))
+ return current;
+
+ d->forcedSelectionPosition = d->elementsInfo[current.row() - 1].relativeOffsetToCategory % elementsPerRow;
+#if 0 //follow qt view behavior. lateral movements won't change visual row
if (d->forcedSelectionPosition < 0)
d->forcedSelectionPosition = (d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow;
+#endif
- return d->elementDictionary[d->proxyModel->index(d->invertedElementDictionary[current].row() - 1, 0)];
+ 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() + 1, 0)])].relativeOffsetToCategory % elementsPerRow;
+ if (layoutDirection() == Qt::RightToLeft)
+ {
+ if (!(d->elementsInfo[current.row()].relativeOffsetToCategory % elementsPerRow))
+ return current;
+
+ d->forcedSelectionPosition = d->elementsInfo[current.row() - 1].relativeOffsetToCategory % elementsPerRow;
+
+#if 0 //follow qt view behavior. lateral movements won't change visual row
+ if (d->forcedSelectionPosition < 0)
+ d->forcedSelectionPosition = (d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow;
+#endif
+
+ return d->proxyModel->index(current.row() - 1, 0);
+ }
+ if (!(d->elementsInfo[current.row() + 1].relativeOffsetToCategory % elementsPerRow))
+ return current;
+
+ d->forcedSelectionPosition = d->elementsInfo[current.row() + 1].relativeOffsetToCategory % elementsPerRow;
+
+#if 0 //follow qt view behavior. lateral movements won't change visual row
if (d->forcedSelectionPosition < 0)
d->forcedSelectionPosition = (d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow;
+#endif
- return d->elementDictionary[d->proxyModel->index(d->invertedElementDictionary[current].row() + 1, 0)];
+ return d->proxyModel->index(current.row() + 1, 0);
default:
break;
}
void KCategorizedView::rowsInserted(const QModelIndex &parent,
- int start,
- int end)
+ int start,
+ int end)
{
QListView::rowsInserted(parent, start, end);
if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->itemCategorizer)
+ !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
{
- d->lastSelection = QItemSelection();
- d->currentViewIndex = QModelIndex();
d->forcedSelectionPosition = 0;
d->elementsInfo.clear();
d->elementsPosition.clear();
- d->elementDictionary.clear();
- d->invertedElementDictionary.clear();
d->categoriesIndexes.clear();
d->categoriesPosition.clear();
d->categories.clear();
d->intersectedIndexes.clear();
- d->sourceModelIndexList.clear();
+ d->modelIndexList.clear();
d->hovered = QModelIndex();
d->biggestItemSize = QSize(0, 0);
d->mouseButtonPressed = false;
+ d->rightMouseButtonPressed = false;
return;
}
}
void KCategorizedView::rowsInsertedArtifficial(const QModelIndex &parent,
- int start,
- int end)
+ int start,
+ int end)
{
Q_UNUSED(parent);
- d->lastSelection = QItemSelection();
- d->currentViewIndex = QModelIndex();
d->forcedSelectionPosition = 0;
d->elementsInfo.clear();
d->elementsPosition.clear();
- d->elementDictionary.clear();
- d->invertedElementDictionary.clear();
d->categoriesIndexes.clear();
d->categoriesPosition.clear();
d->categories.clear();
d->intersectedIndexes.clear();
- d->sourceModelIndexList.clear();
+ d->modelIndexList.clear();
d->hovered = QModelIndex();
d->biggestItemSize = QSize(0, 0);
d->mouseButtonPressed = false;
+ d->rightMouseButtonPressed = false;
if (start > end || end < 0 || start < 0 || !d->proxyModel->rowCount())
{
return;
}
- // Add all elements mapped to the source model
- for (int k = 0; k < d->proxyModel->rowCount(); k++)
+ // Add all elements mapped to the source model and explore categories
+ QString prevCategory = d->proxyModel->data(d->proxyModel->index(0, d->proxyModel->sortColumn()), KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString();
+ QString lastCategory = prevCategory;
+ QModelIndexList modelIndexList;
+ struct Private::ElementInfo elementInfo;
+ int offset = -1;
+ for (int k = 0; k < d->proxyModel->rowCount(); ++k)
{
- d->biggestItemSize = QSize(qMax(sizeHintForIndex(d->proxyModel->index(k, 0)).width(),
+ 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(d->proxyModel->index(k, 0)).height(),
+ qMax(sizeHintForIndex(indexSize).height(),
d->biggestItemSize.height()));
- d->sourceModelIndexList <<
- d->proxyModel->mapToSource(d->proxyModel->index(k, 0));
- }
-
- // Sort them with the general purpose lessThan method
- LessThan generalLessThan(d->proxyModel,
- LessThan::GeneralPurpose);
-
- qStableSort(d->sourceModelIndexList.begin(), d->sourceModelIndexList.end(),
- generalLessThan);
+ d->modelIndexList << index;
- // Explore categories
- QString prevCategory =
- d->itemCategorizer->categoryForItem(d->sourceModelIndexList[0],
- d->proxyModel->sortRole());
- QString lastCategory = prevCategory;
- QModelIndexList modelIndexList;
- struct Private::ElementInfo elementInfo;
- foreach (const QModelIndex &index, d->sourceModelIndexList)
- {
- lastCategory = d->itemCategorizer->categoryForItem(index,
- d->proxyModel->sortRole());
+ lastCategory = d->proxyModel->data(index, KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString();
elementInfo.category = lastCategory;
if (prevCategory != lastCategory)
{
+ offset = 0;
d->categoriesIndexes.insert(prevCategory, modelIndexList);
d->categories << prevCategory;
modelIndexList.clear();
}
+ else
+ {
+ offset++;
+ }
+
+ elementInfo.relativeOffsetToCategory = offset;
modelIndexList << index;
prevCategory = lastCategory;
- d->elementsInfo.insert(index, elementInfo);
+ d->elementsInfo.insert(index.row(), elementInfo);
}
d->categoriesIndexes.insert(prevCategory, modelIndexList);
d->categories << prevCategory;
- // Sort items locally in their respective categories with the category
- // purpose lessThan
- LessThan categoryLessThan(d->proxyModel,
- LessThan::CategoryPurpose);
-
- foreach (const QString &key, d->categories)
- {
- QModelIndexList &indexList = d->categoriesIndexes[key];
-
- qStableSort(indexList.begin(), indexList.end(), categoryLessThan);
- }
-
- d->lastIndex = d->categoriesIndexes[d->categories[d->categories.count() - 1]][d->categoriesIndexes[d->categories[d->categories.count() - 1]].count() - 1];
-
- // Finally, fill data information of items situation. This will help when
- // trying to compute an item place in the viewport
- int i = 0; // position relative to the category beginning
- int j = 0; // number of elements before current
- foreach (const QString &key, d->categories)
- {
- foreach (const QModelIndex &index, d->categoriesIndexes[key])
- {
- struct Private::ElementInfo &elementInfo = d->elementsInfo[index];
-
- elementInfo.relativeOffsetToCategory = i;
-
- d->elementDictionary.insert(d->proxyModel->index(j, 0),
- d->proxyModel->mapFromSource(index));
-
- d->invertedElementDictionary.insert(d->proxyModel->mapFromSource(index),
- d->proxyModel->index(j, 0));
-
- i++;
- j++;
- }
-
- i = 0;
- }
-
d->updateScrollbars();
+
+ // FIXME: We need to safely save the last selection. This is on my TODO
+ // list (ereslibre).
+ selectionModel()->clear();
}
void KCategorizedView::rowsRemoved(const QModelIndex &parent,
- int start,
- int end)
+ int start,
+ int end)
{
if ((viewMode() == KCategorizedView::IconMode) && d->proxyModel &&
- d->itemCategorizer)
+ 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::updateGeometries()
{
if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->itemCategorizer)
+ !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
{
QListView::updateGeometries();
return;
QAbstractItemView::updateGeometries();
}
-void KCategorizedView::slotSortingRoleChanged()
+void KCategorizedView::slotLayoutChanged()
{
- if ((viewMode() == KCategorizedView::IconMode) && d->proxyModel &&
- d->itemCategorizer)
+ d->layoutChanged();
+}
+
+void KCategorizedView::currentChanged(const QModelIndex ¤t,
+ const QModelIndex &previous)
+{
+ // We need to update the forcedSelectionPosition property in order to correctly
+ // navigate after with keyboard using up & down keys
+
+ int viewportWidth = viewport()->width() - spacing();
+
+ int itemHeight;
+ int itemWidth;
+
+ if (gridSize().isEmpty())
{
- // Force the view to update all elements
- rowsInsertedArtifficial(QModelIndex(), 0, d->proxyModel->rowCount() - 1);
+ itemHeight = d->biggestItemSize.height();
+ itemWidth = d->biggestItemSize.width();
}
+ else
+ {
+ itemHeight = gridSize().height();
+ itemWidth = gridSize().width();
+ }
+
+ int itemWidthPlusSeparation = spacing() + itemWidth;
+ int elementsPerRow = viewportWidth / itemWidthPlusSeparation;
+ if (!elementsPerRow)
+ elementsPerRow++;
+
+ if (d->mouseButtonPressed || d->rightMouseButtonPressed)
+ d->forcedSelectionPosition = d->elementsInfo[current.row()].relativeOffsetToCategory % elementsPerRow;
+
+ QListView::currentChanged(current, previous);
}
#include "kcategorizedview.moc"