X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/ce3f4e5d74ce4eeb70d2c61b9a21ca43c0e9228b..3ba0f41c44e41da9606fff05cc21f4344d6f9b5f:/src/kcategorizedview.cpp diff --git a/src/kcategorizedview.cpp b/src/kcategorizedview.cpp index 622fe7b60..5ec751fa4 100644 --- a/src/kcategorizedview.cpp +++ b/src/kcategorizedview.cpp @@ -1,6 +1,6 @@ /** * This file is part of the KDE project - * Copyright (C) 2007 Rafael Fernández López + * Copyright (C) 2007 Rafael Fernández López * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -29,61 +29,19 @@ #include #include -#include #include -#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" KCategorizedView::Private::Private(KCategorizedView *listView) : listView(listView) - , itemCategorizer(0) + , categoryDrawer(0) , biggestItemSize(QSize(0, 0)) , mouseButtonPressed(false) , isDragging(false) , dragLeftViewport(false) , proxyModel(0) - , lastIndex(QModelIndex()) { } @@ -98,6 +56,17 @@ const QModelIndexList &KCategorizedView::Private::intersectionSet(const QRect &r intersectedIndexes.clear(); + int itemHeight; + + if (listView->gridSize().isEmpty()) + { + itemHeight = biggestItemSize.height(); + } + else + { + itemHeight = listView->gridSize().height(); + } + // Lets find out where we should start int top = proxyModel->rowCount() - 1; int bottom = 0; @@ -106,12 +75,15 @@ const QModelIndexList &KCategorizedView::Private::intersectionSet(const QRect &r { 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) + indexVisualRect.setHeight(indexVisualRect.height() + (itemHeight - indexVisualRect.height())); if (qMax(indexVisualRect.topLeft().y(), indexVisualRect.bottomRight().y()) < qMin(rect.topLeft().y(), - rect.bottomRight().y())) + rect.bottomRight().y())) { bottom = middle + 1; } @@ -123,7 +95,7 @@ const QModelIndexList &KCategorizedView::Private::intersectionSet(const QRect &r 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)) @@ -144,25 +116,58 @@ QRect KCategorizedView::Private::visualRectInViewport(const QModelIndex &index) 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(listView->viewOptions()), 0, 0); + } + else + { + retRect = QRect(listView->viewport()->width() - listView->spacing(), listView->spacing() * 2 + + categoryDrawer->categoryHeight(listView->viewOptions()), 0, 0); + } int viewportWidth = listView->viewport()->width() - listView->spacing(); - int itemHeight = biggestItemSize.height(); - int itemWidth = biggestItemSize.width(); + int itemHeight; + int itemWidth; + + if (listView->gridSize().isEmpty()) + { + itemHeight = biggestItemSize.height(); + itemWidth = biggestItemSize.width(); + } + else + { + itemHeight = listView->gridSize().height(); + itemWidth = listView->gridSize().width(); + } + int itemWidthPlusSeparation = listView->spacing() + itemWidth; int elementsPerRow = viewportWidth / itemWidthPlusSeparation; 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; - retRect.setLeft(retRect.left() + column * listView->spacing() + - column * itemWidth); + 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.setRight(retRect.right() - column * listView->spacing() - + column * itemWidth); + } foreach (const QString &category, categories) { @@ -171,22 +176,45 @@ QRect KCategorizedView::Private::visualRectInViewport(const QModelIndex &index) 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 * listView->spacing()) + (rowsInt * itemHeight) + - itemCategorizer->categoryHeight(listView->viewOptions()) + + categoryDrawer->categoryHeight(listView->viewOptions()) + listView->spacing() * 2); + + if (listView->gridSize().isEmpty()) + { + retRect.setTop(retRect.top() + + (rowsInt * listView->spacing())); + } } - retRect.setTop(retRect.top() + row * listView->spacing() + - row * itemHeight); + if (listView->gridSize().isEmpty()) + { + retRect.setTop(retRect.top() + row * listView->spacing() + + (row * itemHeight)); + } + else + { + retRect.setTop(retRect.top() + (row * itemHeight)); + } retRect.setWidth(itemWidth); - retRect.setHeight(itemHeight); + + QModelIndex heightIndex = proxyModel->index(index.row(), 0); + if (listView->gridSize().isEmpty()) + { + retRect.setHeight(listView->sizeHintForIndex(heightIndex).height()); + } + else + { + retRect.setHeight(qMin(listView->sizeHintForIndex(heightIndex).height(), + listView->gridSize().height())); + } return retRect; } @@ -206,8 +234,20 @@ QRect KCategorizedView::Private::visualCategoryRectInViewport(const QString &cat int viewportWidth = listView->viewport()->width() - listView->spacing(); - int itemHeight = biggestItemSize.height(); - int itemWidth = biggestItemSize.width(); + int itemHeight; + int itemWidth; + + if (listView->gridSize().isEmpty()) + { + itemHeight = biggestItemSize.height(); + itemWidth = biggestItemSize.width(); + } + else + { + itemHeight = listView->gridSize().height(); + itemWidth = listView->gridSize().width(); + } + int itemWidthPlusSeparation = listView->spacing() + itemWidth; int elementsPerRow = viewportWidth / itemWidthPlusSeparation; @@ -226,13 +266,18 @@ QRect KCategorizedView::Private::visualCategoryRectInViewport(const QString &cat if (rows - trunc(rows)) rowsInt++; retRect.setTop(retRect.top() + - (rowsInt * listView->spacing()) + (rowsInt * itemHeight) + - itemCategorizer->categoryHeight(listView->viewOptions()) + + categoryDrawer->categoryHeight(listView->viewOptions()) + listView->spacing() * 2); + + if (listView->gridSize().isEmpty()) + { + retRect.setTop(retRect.top() + + (rowsInt * listView->spacing())); + } } - retRect.setHeight(itemCategorizer->categoryHeight(listView->viewOptions())); + retRect.setHeight(categoryDrawer->categoryHeight(listView->viewOptions())); return retRect; } @@ -241,9 +286,9 @@ QRect KCategorizedView::Private::visualCategoryRectInViewport(const QString &cat 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 @@ -257,9 +302,9 @@ const QRect &KCategorizedView::Private::cacheCategory(const QString &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 @@ -281,9 +326,7 @@ const QRect &KCategorizedView::Private::cachedRectCategory(const QString &catego 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); @@ -302,29 +345,50 @@ QRect KCategorizedView::Private::categoryVisualRect(const QString &category) } 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::CategoryRole).toString(); + + optionCopy.state &= ~QStyle::State_Selected; 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() { - int lastItemBottom = cachedRectIndex(lastIndex).bottom() + - listView->spacing() - listView->viewport()->height(); + // 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->verticalScrollBar()->setSingleStep(listView->viewport()->height() / 10); listView->verticalScrollBar()->setPageStep(listView->viewport()->height()); @@ -388,6 +452,13 @@ KCategorizedView::~KCategorizedView() delete d; } +void KCategorizedView::setGridSize(const QSize &size) +{ + QListView::setGridSize(size); + + slotLayoutChanged(); +} + void KCategorizedView::setModel(QAbstractItemModel *model) { d->lastSelection = QItemSelection(); @@ -395,47 +466,45 @@ void KCategorizedView::setModel(QAbstractItemModel *model) 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; 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())); } QListView::setModel(model); - d->proxyModel = dynamic_cast(model); + d->proxyModel = dynamic_cast(model); if (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(sortingRoleChanged()), - this, SLOT(slotSortingRoleChanged())); + SIGNAL(dataChanged(QModelIndex,QModelIndex)), + this, SLOT(slotLayoutChanged())); } } QRect KCategorizedView::visualRect(const QModelIndex &index) const { if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || - !d->itemCategorizer) + !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { return QListView::visualRect(index); } @@ -448,54 +517,55 @@ QRect KCategorizedView::visualRect(const QModelIndex &index) const 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; - 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(sortingRoleChanged()), - this, SLOT(slotSortingRoleChanged())); + SIGNAL(dataChanged(QModelIndex,QModelIndex)), + this, SLOT(slotLayoutChanged())); } - 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(sortingRoleChanged()), - this, SLOT(slotSortingRoleChanged())); + SIGNAL(dataChanged(QModelIndex,QModelIndex)), + this, SLOT(slotLayoutChanged())); } - d->itemCategorizer = itemCategorizer; + d->categoryDrawer = categoryDrawer; - if (itemCategorizer) + if (categoryDrawer) { - rowsInserted(QModelIndex(), 0, d->proxyModel->rowCount() - 1); + if (d->proxyModel) + { + rowsInserted(QModelIndex(), 0, d->proxyModel->rowCount() - 1); + } } else { @@ -506,7 +576,7 @@ void KCategorizedView::setItemCategorizer(KItemCategorizer *itemCategorizer) QModelIndex KCategorizedView::indexAt(const QPoint &point) const { if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || - !d->itemCategorizer) + !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { return QListView::indexAt(point); } @@ -534,13 +604,11 @@ void KCategorizedView::reset() 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; @@ -549,7 +617,7 @@ void KCategorizedView::reset() void KCategorizedView::paintEvent(QPaintEvent *event) { if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || - !d->itemCategorizer) + !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { QListView::paintEvent(event); return; @@ -557,6 +625,11 @@ void KCategorizedView::paintEvent(QPaintEvent *event) QStyleOptionViewItemV3 option = viewOptions(); option.widget = this; + if (wordWrap()) + { + option.features |= QStyleOptionViewItemV2::WrapText; + } + QPainter painter(viewport()); QRect area = event->rect(); const bool focus = (hasFocus() || viewport()->hasFocus()) && @@ -570,7 +643,7 @@ void KCategorizedView::paintEvent(QPaintEvent *event) foreach (const QModelIndex &index, dirtyIndexes) { option.state = state; - option.rect = d->visualRect(index); + option.rect = visualRect(index); if (selectionModel() && selectionModel()->isSelected(index)) { @@ -617,7 +690,9 @@ void KCategorizedView::paintEvent(QPaintEvent *event) if (otherOption.rect.intersects(area)) { - d->drawNewCategory(d->categoriesIndexes[category][0], + QModelIndex indexToDraw = d->proxyModel->index(d->categoriesIndexes[category][0].row(), d->proxyModel->sortColumn()); + + d->drawNewCategory(indexToDraw, d->proxyModel->sortRole(), otherOption, &painter); } } @@ -672,7 +747,7 @@ void KCategorizedView::resizeEvent(QResizeEvent *event) d->forcedSelectionPosition = 0; if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || - !d->itemCategorizer) + !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { return; } @@ -684,7 +759,7 @@ void KCategorizedView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags flags) { if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || - !d->itemCategorizer) + !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { QListView::setSelection(rect, flags); return; @@ -693,20 +768,22 @@ void KCategorizedView::setSelection(const QRect &rect, if (!flags) return; - selectionModel()->clear(); - if (flags & QItemSelectionModel::Clear) { - d->lastSelection = QItemSelection(); + if (!rect.intersects(d->categoryVisualRect(d->hoveredCategory))) + { + d->lastSelection = QItemSelection(); + } } - QModelIndexList dirtyIndexes = d->intersectionSet(rect); + selectionModel()->clear(); - QItemSelection selection; + QModelIndexList dirtyIndexes = d->intersectionSet(rect); if (!dirtyIndexes.count()) { - if (d->lastSelection.count()) + if (!d->lastSelection.isEmpty() && + (rect.intersects(d->categoryVisualRect(d->hoveredCategory)) || d->mouseButtonPressed)) { selectionModel()->select(d->lastSelection, flags); } @@ -714,6 +791,8 @@ void KCategorizedView::setSelection(const QRect &rect, return; } + QItemSelection selection; + if (!d->mouseButtonPressed) { selection = QItemSelection(dirtyIndexes[0], dirtyIndexes[0]); @@ -741,13 +820,12 @@ void KCategorizedView::setSelection(const QRect &rect, selection << QItemSelectionRange(first, last); } - if (d->lastSelection.count() && !d->mouseButtonPressed) + if (d->lastSelection.count()) { - selection.merge(d->lastSelection, flags); - } - else if (d->lastSelection.count()) - { - selection.merge(d->lastSelection, QItemSelectionModel::Select); + if ((selection.count() == 1) && (selection[0].indexes().count() == 1)) + selection.merge(d->lastSelection, flags); + else + selection.merge(d->lastSelection, QItemSelectionModel::Select); } selectionModel()->select(selection, flags); @@ -758,7 +836,7 @@ void KCategorizedView::mouseMoveEvent(QMouseEvent *event) QListView::mouseMoveEvent(event); if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || - !d->itemCategorizer) + !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { return; } @@ -829,6 +907,8 @@ void KCategorizedView::mousePressEvent(QMouseEvent *event) } QListView::mousePressEvent(event); + + viewport()->update(d->categoryVisualRect(d->hoveredCategory)); } void KCategorizedView::mouseReleaseEvent(QMouseEvent *event) @@ -838,7 +918,7 @@ void KCategorizedView::mouseReleaseEvent(QMouseEvent *event) QListView::mouseReleaseEvent(event); if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || - !d->itemCategorizer) + !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { return; } @@ -848,6 +928,7 @@ void KCategorizedView::mouseReleaseEvent(QMouseEvent *event) initialPressPosition.setX(initialPressPosition.x() + horizontalOffset()); QItemSelection selection; + QItemSelection deselection; if (initialPressPosition == d->initialPressPosition) { @@ -857,10 +938,20 @@ void KCategorizedView::mouseReleaseEvent(QMouseEvent *event) { foreach (const QModelIndex &index, d->categoriesIndexes[category]) { - selection << QItemSelectionRange(d->proxyModel->mapFromSource(index)); + QModelIndex selectIndex = index.model()->index(index.row(), 0); + + if (!d->lastSelection.contains(selectIndex)) + { + selection << QItemSelectionRange(selectIndex); + } + else + { + deselection << QItemSelectionRange(selectIndex); + } } selectionModel()->select(selection, QItemSelectionModel::Select); + selectionModel()->select(deselection, QItemSelectionModel::Deselect); break; } @@ -870,7 +961,7 @@ void KCategorizedView::mouseReleaseEvent(QMouseEvent *event) d->lastSelection = selectionModel()->selection(); if (d->hovered.isValid()) - viewport()->update(d->visualRect(d->hovered)); + viewport()->update(visualRect(d->hovered)); else if (!d->hoveredCategory.isEmpty()) viewport()->update(d->categoryVisualRect(d->hoveredCategory)); } @@ -909,7 +1000,7 @@ void KCategorizedView::dragMoveEvent(QDragMoveEvent *event) d->dragLeftViewport = false; if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || - !d->itemCategorizer) + !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { QListView::dragMoveEvent(event); return; @@ -928,8 +1019,12 @@ void KCategorizedView::dragLeaveEvent(QDragLeaveEvent *event) QModelIndex KCategorizedView::moveCursor(CursorAction cursorAction, 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); } @@ -937,13 +1032,24 @@ QModelIndex KCategorizedView::moveCursor(CursorAction cursorAction, const QModelIndex current = selectionModel()->currentIndex(); int viewportWidth = viewport()->width() - spacing(); - int itemWidth = d->biggestItemSize.width(); + int itemWidth; + + if (gridSize().isEmpty()) + { + itemWidth = d->biggestItemSize.width(); + } + else + { + itemWidth = gridSize().width(); + } + int itemWidthPlusSeparation = spacing() + itemWidth; int elementsPerRow = viewportWidth / itemWidthPlusSeparation; - QString lastCategory = d->categories[0]; - QString theCategory = d->categories[0]; - QString afterCategory = d->categories[0]; + QString lastCategory = d->categories.first(); + QString theCategory = d->categories.first(); + QString afterCategory = d->categories.first(); + bool hasToBreak = false; foreach (const QString &category, d->categories) { @@ -954,7 +1060,7 @@ QModelIndex KCategorizedView::moveCursor(CursorAction cursorAction, break; } - if (category == d->elementsInfo[d->proxyModel->mapToSource(current)].category) + if (category == d->elementsInfo[current.row()].category) { theCategory = category; @@ -970,17 +1076,17 @@ QModelIndex KCategorizedView::moveCursor(CursorAction cursorAction, 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) { @@ -991,22 +1097,22 @@ QModelIndex KCategorizedView::moveCursor(CursorAction cursorAction, 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) { @@ -1017,25 +1123,25 @@ QModelIndex KCategorizedView::moveCursor(CursorAction cursorAction, 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; + 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() - 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; + 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() + 1, 0)]; + return d->proxyModel->index(current.row() + 1, 0); default: break; @@ -1051,20 +1157,18 @@ void KCategorizedView::rowsInserted(const QModelIndex &parent, 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; @@ -1086,13 +1190,11 @@ void KCategorizedView::rowsInsertedArtifficial(const QModelIndex &parent, 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; @@ -1110,86 +1212,44 @@ void KCategorizedView::rowsInsertedArtifficial(const QModelIndex &parent, qMax(sizeHintForIndex(d->proxyModel->index(k, 0)).height(), d->biggestItemSize.height())); - d->sourceModelIndexList << - d->proxyModel->mapToSource(d->proxyModel->index(k, 0)); + d->modelIndexList << d->proxyModel->index(k, d->proxyModel->sortColumn()); } - // Sort them with the general purpose lessThan method - LessThan generalLessThan(d->proxyModel, - LessThan::GeneralPurpose); - - qStableSort(d->sourceModelIndexList.begin(), d->sourceModelIndexList.end(), - generalLessThan); - // Explore categories - QString prevCategory = - d->itemCategorizer->categoryForItem(d->sourceModelIndexList[0], - d->proxyModel->sortRole()); + QString prevCategory = d->proxyModel->data(d->modelIndexList[0], KCategorizedSortFilterProxyModel::CategoryRole).toString(); QString lastCategory = prevCategory; QModelIndexList modelIndexList; struct Private::ElementInfo elementInfo; - foreach (const QModelIndex &index, d->sourceModelIndexList) + int offset = -1; + foreach (const QModelIndex &index, d->modelIndexList) { - lastCategory = d->itemCategorizer->categoryForItem(index, - d->proxyModel->sortRole()); + lastCategory = d->proxyModel->data(index, KCategorizedSortFilterProxyModel::CategoryRole).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(); } @@ -1198,7 +1258,7 @@ void KCategorizedView::rowsRemoved(const QModelIndex &parent, 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); @@ -1208,7 +1268,7 @@ void KCategorizedView::rowsRemoved(const QModelIndex &parent, void KCategorizedView::updateGeometries() { if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || - !d->itemCategorizer) + !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { QListView::updateGeometries(); return; @@ -1219,10 +1279,10 @@ void KCategorizedView::updateGeometries() QAbstractItemView::updateGeometries(); } -void KCategorizedView::slotSortingRoleChanged() +void KCategorizedView::slotLayoutChanged() { if ((viewMode() == KCategorizedView::IconMode) && d->proxyModel && - d->itemCategorizer) + d->categoryDrawer && d->proxyModel->isCategorizedModel()) { // Force the view to update all elements rowsInsertedArtifficial(QModelIndex(), 0, d->proxyModel->rowCount() - 1);