X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/d351d41e4bfd982646d7919b7eeb2cf98992edc3..1e27cae3e58f0be65ea6c690f9144b0621829d2b:/src/kcategorizedview.cpp diff --git a/src/kcategorizedview.cpp b/src/kcategorizedview.cpp index 72936113c..42ee7b1ad 100644 --- a/src/kcategorizedview.cpp +++ b/src/kcategorizedview.cpp @@ -44,6 +44,7 @@ KCategorizedView::Private::Private(KCategorizedView *listView) , categoryDrawer(0) , biggestItemSize(QSize(0, 0)) , mouseButtonPressed(false) + , rightMouseButtonPressed(false) , isDragging(false) , dragLeftViewport(false) , proxyModel(0) @@ -499,7 +500,6 @@ void KCategorizedView::setGridSize(const QSize &size) void KCategorizedView::setModel(QAbstractItemModel *model) { d->lastSelection = QItemSelection(); - d->currentViewIndex = QModelIndex(); d->forcedSelectionPosition = 0; d->elementsInfo.clear(); d->elementsPosition.clear(); @@ -510,6 +510,7 @@ void KCategorizedView::setModel(QAbstractItemModel *model) d->modelIndexList.clear(); d->hovered = QModelIndex(); d->mouseButtonPressed = false; + d->rightMouseButtonPressed = false; if (d->proxyModel) { @@ -585,7 +586,6 @@ KCategoryDrawer *KCategorizedView::categoryDrawer() const void KCategorizedView::setCategoryDrawer(KCategoryDrawer *categoryDrawer) { d->lastSelection = QItemSelection(); - d->currentViewIndex = QModelIndex(); d->forcedSelectionPosition = 0; d->elementsInfo.clear(); d->elementsPosition.clear(); @@ -596,6 +596,7 @@ void KCategorizedView::setCategoryDrawer(KCategoryDrawer *categoryDrawer) d->modelIndexList.clear(); d->hovered = QModelIndex(); d->mouseButtonPressed = false; + d->rightMouseButtonPressed = false; if (!categoryDrawer && d->proxyModel) { @@ -661,8 +662,6 @@ QModelIndex KCategorizedView::indexAt(const QPoint &point) const index = item[0]; } - d->hovered = index; - return index; } @@ -671,7 +670,6 @@ void KCategorizedView::reset() QListView::reset(); d->lastSelection = QItemSelection(); - d->currentViewIndex = QModelIndex(); d->forcedSelectionPosition = 0; d->elementsInfo.clear(); d->elementsPosition.clear(); @@ -683,6 +681,7 @@ void KCategorizedView::reset() d->hovered = QModelIndex(); d->biggestItemSize = QSize(0, 0); d->mouseButtonPressed = false; + d->rightMouseButtonPressed = false; } void KCategorizedView::paintEvent(QPaintEvent *event) @@ -743,7 +742,10 @@ void KCategorizedView::paintEvent(QPaintEvent *event) 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; @@ -849,88 +851,130 @@ void KCategorizedView::setSelection(const QRect &rect, if (flags & QItemSelectionModel::Clear) { - if (!rect.intersects(d->categoryVisualRect(d->hoveredCategory))) - { - d->lastSelection = QItemSelection(); - } + selectionModel()->clear(); + d->lastSelection.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, QItemSelectionModel::SelectCurrent); return; } - int viewportWidth = viewport()->width() - spacing(); - int itemWidth; + QModelIndex topLeft; + QModelIndex bottomRight; - if (gridSize().isEmpty()) - { - itemWidth = d->biggestItemSize.width(); - } - else + if (d->mouseButtonPressed || d->rightMouseButtonPressed) // selection with click + drag { - itemWidth = gridSize().width(); - } + QItemSelection selection; - int itemWidthPlusSeparation = spacing() + itemWidth; - int elementsPerRow = viewportWidth / itemWidthPlusSeparation; - - QItemSelection selection; - - if (!d->mouseButtonPressed) - { - selection = QItemSelection(dirtyIndexes[0], dirtyIndexes[0]); - d->currentViewIndex = dirtyIndexes[0]; - selectionModel()->setCurrentIndex(d->currentViewIndex, flags); - d->forcedSelectionPosition = d->elementsInfo[d->currentViewIndex.row()].relativeOffsetToCategory % elementsPerRow; - } - else - { - 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; + // 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 (first == last) + if (flags & QItemSelectionModel::Current) { - selectionModel()->setCurrentIndex(first, QItemSelectionModel::SelectCurrent); - d->forcedSelectionPosition = d->elementsInfo[first.row()].relativeOffsetToCategory % elementsPerRow; - } - } + if (rect.topLeft() == rect.bottomRight()) + { + selectionModel()->setCurrentIndex(indexAt(rect.topLeft()), QItemSelectionModel::NoUpdate); + } - if (d->lastSelection.count()) - { - if ((selection.count() == 1) && (selection[0].indexes().count() == 1)) selection.merge(d->lastSelection, flags); + } else - selection.merge(d->lastSelection, QItemSelectionModel::Select); + { + selection.merge(selectionModel()->selection(), flags); + + selectionModel()->select(selection, QItemSelectionModel::SelectCurrent); + + return; + } + + selectionModel()->select(selection, flags); } + else // selection with click + keyboard keys + { + 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 + { + 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); + selectionModel()->select(selection, flags); + } } void KCategorizedView::mouseMoveEvent(QMouseEvent *event) @@ -943,6 +987,17 @@ void KCategorizedView::mouseMoveEvent(QMouseEvent *event) 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(); @@ -986,10 +1041,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; } } @@ -1007,15 +1058,22 @@ void KCategorizedView::mousePressEvent(QMouseEvent *event) 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); @@ -1029,39 +1087,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); break; } } } - d->lastSelection = selectionModel()->selection(); - if (d->hovered.isValid()) viewport()->update(visualRect(d->hovered)); else if (!d->hoveredCategory.isEmpty()) @@ -1089,6 +1137,7 @@ void KCategorizedView::startDrag(Qt::DropActions supportedActions) d->isDragging = false; d->mouseButtonPressed = false; + d->rightMouseButtonPressed = false; viewport()->update(d->lastDraggedItemsRect); } @@ -1155,7 +1204,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()); + selectionModel()->select(current, QItemSelectionModel::NoUpdate); + d->forcedSelectionPosition = 0; + + return current; + } int viewportWidth = viewport()->width() - spacing(); int itemWidth; @@ -1171,6 +1229,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(); @@ -1256,36 +1316,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); @@ -1305,8 +1385,6 @@ void KCategorizedView::rowsInserted(const QModelIndex &parent, if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { - d->lastSelection = QItemSelection(); - d->currentViewIndex = QModelIndex(); d->forcedSelectionPosition = 0; d->elementsInfo.clear(); d->elementsPosition.clear(); @@ -1318,6 +1396,7 @@ void KCategorizedView::rowsInserted(const QModelIndex &parent, d->hovered = QModelIndex(); d->biggestItemSize = QSize(0, 0); d->mouseButtonPressed = false; + d->rightMouseButtonPressed = false; return; } @@ -1331,8 +1410,6 @@ void KCategorizedView::rowsInsertedArtifficial(const QModelIndex &parent, { Q_UNUSED(parent); - d->lastSelection = QItemSelection(); - d->currentViewIndex = QModelIndex(); d->forcedSelectionPosition = 0; d->elementsInfo.clear(); d->elementsPosition.clear(); @@ -1344,6 +1421,7 @@ void KCategorizedView::rowsInsertedArtifficial(const QModelIndex &parent, d->hovered = QModelIndex(); d->biggestItemSize = QSize(0, 0); d->mouseButtonPressed = false; + d->rightMouseButtonPressed = false; if (start > end || end < 0 || start < 0 || !d->proxyModel->rowCount()) { @@ -1396,6 +1474,10 @@ void KCategorizedView::rowsInsertedArtifficial(const QModelIndex &parent, d->categories << prevCategory; 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, @@ -1429,4 +1511,36 @@ void KCategorizedView::slotLayoutChanged() 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()) + { + 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++; + + d->forcedSelectionPosition = d->elementsInfo[current.row()].relativeOffsetToCategory % elementsPerRow; + + QListView::currentChanged(current, previous); +} + #include "kcategorizedview.moc"