, categoryDrawer(0)
, biggestItemSize(QSize(0, 0))
, mouseButtonPressed(false)
+ , rightMouseButtonPressed(false)
, isDragging(false)
, dragLeftViewport(false)
, proxyModel(0)
if (listView->layoutDirection() == Qt::LeftToRight)
{
retRect = QRect(listView->spacing(), listView->spacing() * 2 +
- categoryDrawer->categoryHeight(listView->viewOptions()), 0, 0);
+ categoryDrawer->categoryHeight(index, listView->viewOptions()), 0, 0);
}
else
{
retRect = QRect(listView->viewport()->width() - listView->spacing(), listView->spacing() * 2 +
- categoryDrawer->categoryHeight(listView->viewOptions()), 0, 0);
+ categoryDrawer->categoryHeight(index, listView->viewOptions()), 0, 0);
}
int viewportWidth = listView->viewport()->width() - listView->spacing();
retRect.setTop(retRect.top() +
(rowsInt * itemHeight) +
- categoryDrawer->categoryHeight(listView->viewOptions()) +
+ categoryDrawer->categoryHeight(index, listView->viewOptions()) +
listView->spacing() * 2);
if (listView->gridSize().isEmpty())
retRect.setTop(retRect.top() +
(rowsInt * itemHeight) +
- categoryDrawer->categoryHeight(listView->viewOptions()) +
+ categoryDrawer->categoryHeight(index, listView->viewOptions()) +
listView->spacing() * 2);
if (listView->gridSize().isEmpty())
}
}
- retRect.setHeight(categoryDrawer->categoryHeight(listView->viewOptions()));
+ retRect.setHeight(categoryDrawer->categoryHeight(index, listView->viewOptions()));
return retRect;
}
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)
+ if ((listView->selectionMode() != SingleSelection) && (listView->selectionMode() != NoSelection)) {
+ if ((category == hoveredCategory) && !mouseButtonPressed)
+ {
+ optionCopy.state |= QStyle::State_MouseOver;
+ }
+ else if ((category == hoveredCategory) && mouseButtonPressed)
{
- optionCopy.state |= QStyle::State_Selected;
+ 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;
+ }
}
}
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);
void KCategorizedView::setModel(QAbstractItemModel *model)
{
d->lastSelection = QItemSelection();
- d->currentViewIndex = QModelIndex();
d->forcedSelectionPosition = 0;
d->elementsInfo.clear();
d->elementsPosition.clear();
d->modelIndexList.clear();
d->hovered = QModelIndex();
d->mouseButtonPressed = false;
+ d->rightMouseButtonPressed = false;
if (d->proxyModel)
{
void KCategorizedView::setCategoryDrawer(KCategoryDrawer *categoryDrawer)
{
d->lastSelection = QItemSelection();
- d->currentViewIndex = QModelIndex();
d->forcedSelectionPosition = 0;
d->elementsInfo.clear();
d->elementsPosition.clear();
d->modelIndexList.clear();
d->hovered = QModelIndex();
d->mouseButtonPressed = false;
+ d->rightMouseButtonPressed = false;
if (!categoryDrawer && d->proxyModel)
{
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->hovered = QModelIndex();
d->biggestItemSize = QSize(0, 0);
d->mouseButtonPressed = false;
+ d->rightMouseButtonPressed = false;
}
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;
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
+ // 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)
if (flags & QItemSelectionModel::Clear)
{
selectionModel()->clear();
+ d->lastSelection.clear();
}
QModelIndexList dirtyIndexes = d->intersectionSet(rect);
// no items affected, just leave
if (!dirtyIndexes.count())
{
- selectionModel()->select(d->lastSelection, flags);
-
- d->lastSelection.clear();
-
- return;
- }
-
- d->lastSelection.clear();
-
- if (!(flags & QItemSelectionModel::Current))
- {
- Q_ASSERT(dirtyIndexes.count() == 1);
-
- selectionModel()->select(dirtyIndexes[0], flags);
+ selectionModel()->select(d->lastSelection, QItemSelectionModel::SelectCurrent);
return;
}
QModelIndex topLeft;
QModelIndex bottomRight;
- if (d->mouseButtonPressed) // selection with click + drag
+ if (d->mouseButtonPressed || d->rightMouseButtonPressed) // selection with click + drag
{
+ QItemSelection selection;
+
QModelIndex prev = dirtyIndexes[0];
QModelIndex first = prev;
foreach (const QModelIndex &index, dirtyIndexes)
{
+ // we have a different interval. non-contiguous items
if ((index.row() - prev.row()) > 1) {
- d->lastSelection << QItemSelectionRange(first, prev);
+ selection << QItemSelectionRange(first, prev);
first = index;
}
prev = index;
}
- d->lastSelection << QItemSelectionRange(first, prev);
+ selection << QItemSelectionRange(first, prev);
+
+ if (flags & QItemSelectionModel::Current)
+ {
+ if (rect.topLeft() == rect.bottomRight())
+ {
+ selectionModel()->setCurrentIndex(indexAt(rect.topLeft()), QItemSelectionModel::NoUpdate);
+ }
- selectionModel()->select(d->lastSelection, flags);
+ selection.merge(d->lastSelection, flags);
+ }
+ else
+ {
+ selection.merge(selectionModel()->selection(), flags);
+
+ selectionModel()->select(selection, QItemSelectionModel::SelectCurrent);
+
+ return;
+ }
+
+ selectionModel()->select(selection, flags);
}
else // selection with click + keyboard keys
{
dirtyIndexes << model()->index(i, theoricDirty[0].column(), theoricDirty[0].parent());
}
- // our current selection will result modified
- d->lastSelection = QItemSelection(topLeft, bottomRight);
+ QItemSelection selection(topLeft, bottomRight);
- selectionModel()->select(d->lastSelection, flags);
+ selectionModel()->select(selection, flags);
}
}
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));
+ 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);
}
}
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);
initialPressPosition.setY(initialPressPosition.y() + verticalOffset());
initialPressPosition.setX(initialPressPosition.x() + horizontalOffset());
- 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()))
{
- QItemSelection selection;
+ QItemSelection selection = selectionModel()->selection();
QModelIndexList indexList = d->categoriesIndexes[category];
foreach (const QModelIndex &index, indexList)
}
}
+ 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));
else if (!d->hoveredCategory.isEmpty())
d->isDragging = false;
d->mouseButtonPressed = false;
+ d->rightMouseButtonPressed = false;
viewport()->update(d->lastDraggedItemsRect);
}
d->dragLeftViewport = false;
- if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
- {
#if defined(DOLPHIN_DRAGANDDROP)
- QAbstractItemView::dragMoveEvent(event);
+ QAbstractItemView::dragMoveEvent(event);
#else
- QListView::dragMoveEvent(event);
+ QListView::dragMoveEvent(event);
#endif
+
+ if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
+ !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
+ {
return;
}
return QListView::moveCursor(cursorAction, modifiers);
}
- 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;
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();
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();
d->hovered = QModelIndex();
d->biggestItemSize = QSize(0, 0);
d->mouseButtonPressed = false;
+ d->rightMouseButtonPressed = false;
return;
}
{
Q_UNUSED(parent);
- d->lastSelection = QItemSelection();
- d->currentViewIndex = QModelIndex();
d->forcedSelectionPosition = 0;
d->elementsInfo.clear();
d->elementsPosition.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())
{
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,
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++;
+
+ if (d->mouseButtonPressed || d->rightMouseButtonPressed)
+ d->forcedSelectionPosition = d->elementsInfo[current.row()].relativeOffsetToCategory % elementsPerRow;
+
+ QListView::currentChanged(current, previous);
+}
+
#include "kcategorizedview.moc"