X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/72dc6a9d229e581eeef26b07108f5883f12b30f0..ff53c10f6c3e9d12d90221a5da5d0a465796fae5:/src/kcategorizedview.cpp diff --git a/src/kcategorizedview.cpp b/src/kcategorizedview.cpp index 4f542f9c7..6590c4b2a 100644 --- a/src/kcategorizedview.cpp +++ b/src/kcategorizedview.cpp @@ -24,7 +24,6 @@ #include // trunc on C99 compliant systems #include // trunc for not C99 compliant systems -#include #include #include #include @@ -34,6 +33,12 @@ #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) @@ -355,7 +360,7 @@ void KCategorizedView::Private::drawNewCategory(const QModelIndex &index, } QStyleOption optionCopy = option; - const QString category = proxyModel->data(index, KCategorizedSortFilterProxyModel::CategoryRole).toString(); + const QString category = proxyModel->data(index, KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString(); optionCopy.state &= ~QStyle::State_Selected; @@ -844,65 +849,122 @@ void KCategorizedView::setSelection(const QRect &rect, if (flags & QItemSelectionModel::Clear) { - if (!rect.intersects(d->categoryVisualRect(d->hoveredCategory))) - { - d->lastSelection = QItemSelection(); - } + selectionModel()->clear(); } - selectionModel()->clear(); - QModelIndexList dirtyIndexes = d->intersectionSet(rect); + // no items affected, just leave if (!dirtyIndexes.count()) { - if (!d->lastSelection.isEmpty() && - (rect.intersects(d->categoryVisualRect(d->hoveredCategory)) || d->mouseButtonPressed)) - { - selectionModel()->select(d->lastSelection, flags); - } + selectionModel()->select(d->lastSelection, flags); + + d->lastSelection.clear(); return; } - QItemSelection selection; + d->lastSelection.clear(); - if (!d->mouseButtonPressed) + if (!(flags & QItemSelectionModel::Current)) { - selection = QItemSelection(dirtyIndexes[0], dirtyIndexes[0]); - d->currentViewIndex = dirtyIndexes[0]; + Q_ASSERT(dirtyIndexes.count() == 1); + + selectionModel()->select(dirtyIndexes[0], flags); + + return; } - else + + QModelIndex topLeft; + QModelIndex bottomRight; + + if (d->mouseButtonPressed) // selection with click + drag { - QModelIndex first = dirtyIndexes[0]; - QModelIndex last; + 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; + if ((index.row() - prev.row()) > 1) { + d->lastSelection << QItemSelectionRange(first, prev); first = index; } - last = index; + prev = index; } - if (last.isValid()) - selection << QItemSelectionRange(first, last); - } + d->lastSelection << QItemSelectionRange(first, prev); - if (d->lastSelection.count()) + selectionModel()->select(d->lastSelection, flags); + } + else // selection with click + keyboard keys { - if ((selection.count() == 1) && (selection[0].indexes().count() == 1)) - selection.merge(d->lastSelection, flags); + 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; + } + + int viewportWidth = viewport()->width() - spacing(); + int itemWidth; + + if (gridSize().isEmpty()) + { + itemWidth = d->biggestItemSize.width(); + } else - selection.merge(d->lastSelection, QItemSelectionModel::Select); - } + { + itemWidth = gridSize().width(); + } + + int itemWidthPlusSeparation = spacing() + itemWidth; + int elementsPerRow = viewportWidth / itemWidthPlusSeparation; + if (!elementsPerRow) + elementsPerRow++; - selectionModel()->select(selection, flags); + 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()); + } + + // our current selection will result modified + d->lastSelection = QItemSelection(topLeft, bottomRight); + + selectionModel()->select(d->lastSelection, flags); + } } void KCategorizedView::mouseMoveEvent(QMouseEvent *event) @@ -958,10 +1020,6 @@ void KCategorizedView::mouseMoveEvent(QMouseEvent *event) } rect = QRect(start, end).intersected(viewport()->rect().adjusted(-16, -16, 16, 16)); - - //viewport()->update(rect.united(d->lastSelectionRect)); - - d->lastSelectionRect = rect; } } @@ -1001,39 +1059,29 @@ void KCategorizedView::mouseReleaseEvent(QMouseEvent *event) initialPressPosition.setY(initialPressPosition.y() + verticalOffset()); initialPressPosition.setX(initialPressPosition.x() + horizontalOffset()); - QItemSelection selection; - QItemSelection deselection; - if (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; + QModelIndexList indexList = d->categoriesIndexes[category]; + + foreach (const QModelIndex &index, indexList) { QModelIndex selectIndex = index.model()->index(index.row(), 0); - if (!d->lastSelection.contains(selectIndex)) - { - selection << QItemSelectionRange(selectIndex); - } - else - { - deselection << QItemSelectionRange(selectIndex); - } + selection << QItemSelectionRange(selectIndex); } - selectionModel()->select(selection, QItemSelectionModel::Select); - selectionModel()->select(deselection, QItemSelectionModel::Deselect); + selectionModel()->select(selection, QItemSelectionModel::SelectCurrent); break; } } } - d->lastSelection = selectionModel()->selection(); - if (d->hovered.isValid()) viewport()->update(visualRect(d->hovered)); else if (!d->hoveredCategory.isEmpty()) @@ -1055,7 +1103,9 @@ void KCategorizedView::startDrag(Qt::DropActions supportedActions) // 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; @@ -1081,7 +1131,11 @@ void KCategorizedView::dragMoveEvent(QDragMoveEvent *event) if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { +#if defined(DOLPHIN_DRAGANDDROP) + QAbstractItemView::dragMoveEvent(event); +#else QListView::dragMoveEvent(event); +#endif return; } @@ -1092,7 +1146,20 @@ void KCategorizedView::dragLeaveEvent(QDragLeaveEvent *event) { 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, @@ -1108,7 +1175,16 @@ QModelIndex KCategorizedView::moveCursor(CursorAction cursorAction, return QListView::moveCursor(cursorAction, modifiers); } - const QModelIndex current = selectionModel()->currentIndex(); + QModelIndex current = selectionModel()->currentIndex(); + + if (!current.isValid()) + { + current = model()->index(0, 0, QModelIndex()); + setCurrentIndex(current); + d->forcedSelectionPosition = 0; + + return current; + } int viewportWidth = viewport()->width() - spacing(); int itemWidth; @@ -1124,6 +1200,8 @@ QModelIndex KCategorizedView::moveCursor(CursorAction cursorAction, int itemWidthPlusSeparation = spacing() + itemWidth; int elementsPerRow = viewportWidth / itemWidthPlusSeparation; + if (!elementsPerRow) + elementsPerRow++; QString lastCategory = d->categories.first(); QString theCategory = d->categories.first(); @@ -1209,36 +1287,56 @@ QModelIndex KCategorizedView::moveCursor(CursorAction cursorAction, case QAbstractItemView::MoveLeft: 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->proxyModel->index(current.row() - 1, 0); case QAbstractItemView::MoveRight: 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->proxyModel->index(current.row() + 1, 0); @@ -1304,7 +1402,7 @@ void KCategorizedView::rowsInsertedArtifficial(const QModelIndex &parent, } // 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 prevCategory = d->proxyModel->data(d->proxyModel->index(0, d->proxyModel->sortColumn()), KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString(); QString lastCategory = prevCategory; QModelIndexList modelIndexList; struct Private::ElementInfo elementInfo; @@ -1321,7 +1419,7 @@ void KCategorizedView::rowsInsertedArtifficial(const QModelIndex &parent, d->modelIndexList << index; - lastCategory = d->proxyModel->data(index, KCategorizedSortFilterProxyModel::CategoryRole).toString(); + lastCategory = d->proxyModel->data(index, KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString(); elementInfo.category = lastCategory;