X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/4905667ada4ddd0aee3d2bb077e401a4262804b9..5070666ad2cd5fe3e559adca00a52aed5d137153:/src/kitemviews/kitemlistcontroller.cpp diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp index ddae06c17..ed23dd1f7 100644 --- a/src/kitemviews/kitemlistcontroller.cpp +++ b/src/kitemviews/kitemlistcontroller.cpp @@ -25,6 +25,7 @@ #include "kitemlistview.h" #include "kitemlistrubberband_p.h" #include "kitemlistselectionmanager.h" +#include "kitemlistkeyboardsearchmanager_p.h" #include #include @@ -37,15 +38,17 @@ KItemListController::KItemListController(QObject* parent) : QObject(parent), - m_dragging(false), m_selectionBehavior(NoSelection), m_model(0), m_view(0), m_selectionManager(new KItemListSelectionManager(this)), + m_keyboardManager(new KItemListKeyboardSearchManager(this)), m_pressedIndex(-1), m_pressedMousePos(), m_oldSelection() { + connect(m_keyboardManager, SIGNAL(changeCurrentItem(QString,bool)), + this, SLOT(slotChangeCurrentItem(QString,bool))); } KItemListController::~KItemListController() @@ -197,15 +200,22 @@ bool KItemListController::keyPressEvent(QKeyEvent* event) } break; + case Qt::Key_Enter: + case Qt::Key_Return: + emit itemActivated(index); + break; + case Qt::Key_Space: if (controlPressed) { m_selectionManager->endAnchoredSelection(); m_selectionManager->setSelected(index, 1, KItemListSelectionManager::Toggle); m_selectionManager->beginAnchoredSelection(index); + break; } default: - break; + m_keyboardManager->addKeys(event->text()); + return false; } if (m_selectionManager->currentItem() != index) { @@ -227,6 +237,27 @@ bool KItemListController::keyPressEvent(QKeyEvent* event) return true; } +void KItemListController::slotChangeCurrentItem(const QString& text, bool searchFromNextItem) +{ + if (!m_model) { + return; + } + const int currentIndex = m_selectionManager->currentItem(); + int index; + if (searchFromNextItem) { + index = m_model->indexForKeyboardSearch(text, (currentIndex + 1) % m_model->count()); + } + else { + index = m_model->indexForKeyboardSearch(text, currentIndex); + } + if (index >= 0) { + m_selectionManager->setCurrentItem(index); + m_selectionManager->clearSelection(); + m_selectionManager->setSelected(index, 1); + m_selectionManager->beginAnchoredSelection(index); + } +} + bool KItemListController::inputMethodEvent(QInputMethodEvent* event) { Q_UNUSED(event); @@ -239,11 +270,11 @@ bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const return false; } - m_dragging = false; m_pressedMousePos = transform.map(event->pos()); m_pressedIndex = m_view->itemAt(m_pressedMousePos); if (m_view->isAboveExpansionToggle(m_pressedIndex, m_pressedMousePos)) { + m_selectionManager->setCurrentItem(m_pressedIndex); return true; } @@ -274,6 +305,11 @@ bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const if (controlPressed) { m_selectionManager->setSelected(m_pressedIndex, 1, KItemListSelectionManager::Toggle); m_selectionManager->beginAnchoredSelection(m_pressedIndex); + } else if (event->buttons() & Qt::RightButton) { + // Only clear the selection if a context menu is requested above a non-selected item + if (!m_selectionManager->selectedItems().contains(m_pressedIndex)) { + m_selectionManager->setSelectedItems(QSet() << m_pressedIndex); + } } else if (!shiftPressed || !m_selectionManager->isAnchoredSelectionActive()) { // Select the pressed item and start a new anchored selection m_selectionManager->setSelected(m_pressedIndex, 1, KItemListSelectionManager::Select); @@ -288,6 +324,10 @@ bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const return true; } else { + if (event->buttons() & Qt::RightButton) { + m_selectionManager->clearSelection(); + } + KItemListRubberBand* rubberBand = m_view->rubberBand(); QPointF startPos = m_pressedMousePos; if (m_view->scrollOrientation() == Qt::Vertical) { @@ -306,6 +346,7 @@ bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const rubberBand->setEndPosition(startPos); rubberBand->setActive(true); connect(rubberBand, SIGNAL(endPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandChanged())); + m_view->setAutoScroll(true); } return false; @@ -319,13 +360,13 @@ bool KItemListController::mouseMoveEvent(QGraphicsSceneMouseEvent* event, const if (m_pressedIndex >= 0) { // Check whether a dragging should be started - if (!m_dragging && (event->buttons() & Qt::LeftButton)) { + if (event->buttons() & Qt::LeftButton) { const QPointF pos = transform.map(event->pos()); const qreal minDragDiff = 4; const bool hasMinDragDiff = qAbs(pos.x() - m_pressedMousePos.x()) >= minDragDiff || qAbs(pos.y() - m_pressedMousePos.y()) >= minDragDiff; - if (hasMinDragDiff && startDragging()) { - m_dragging = true; + if (hasMinDragDiff) { + startDragging(); } } } else { @@ -358,13 +399,14 @@ bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, con const bool shiftOrControlPressed = event->modifiers() & Qt::ShiftModifier || event->modifiers() & Qt::ControlModifier; - bool clearSelection = !shiftOrControlPressed && !m_dragging && !(event->button() == Qt::RightButton); + bool clearSelection = !shiftOrControlPressed && event->button() != Qt::RightButton; KItemListRubberBand* rubberBand = m_view->rubberBand(); if (rubberBand->isActive()) { disconnect(rubberBand, SIGNAL(endPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandChanged())); rubberBand->setActive(false); m_oldSelection.clear(); + m_view->setAutoScroll(false); if (rubberBand->startPosition() != rubberBand->endPosition()) { clearSelection = false; @@ -382,24 +424,29 @@ bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, con m_selectionManager->setSelectedItems(QSet() << index); } - bool emitItemClicked = true; if (event->button() & Qt::LeftButton) { + bool emitItemActivated = true; if (m_view->isAboveExpansionToggle(index, pos)) { emit itemExpansionToggleClicked(index); - emitItemClicked = false; - } else if (shiftOrControlPressed || !KGlobalSettings::singleClick()) { - emitItemClicked = false; + emitItemActivated = false; + } else if (shiftOrControlPressed) { + // The mouse click should only update the selection, not trigger the item + emitItemActivated = false; + } else if (!KGlobalSettings::singleClick()) { + emitItemActivated = false; } - } - - if (emitItemClicked) { - emit itemClicked(index, event->button()); + if (emitItemActivated) { + emit itemActivated(index); + } + } else if (event->button() & Qt::MidButton) { + emit itemMiddleClicked(index); + } else if (event->button() & Qt::RightButton) { + emit contextMenuRequested(index, QPointF(event->pos())); } } else if (clearSelection) { m_selectionManager->clearSelection(); } - m_dragging = false; m_pressedMousePos = QPointF(); m_pressedIndex = -1; return false; @@ -410,11 +457,11 @@ bool KItemListController::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event, const QPointF pos = transform.map(event->pos()); const int index = m_view->itemAt(pos); - bool emitItemClicked = !KGlobalSettings::singleClick() && + bool emitItemActivated = !KGlobalSettings::singleClick() && (event->button() & Qt::LeftButton) && index >= 0 && index < m_model->count(); - if (emitItemClicked) { - emit itemClicked(index, event->button()); + if (emitItemActivated) { + emit itemActivated(index); } return false; } @@ -435,18 +482,43 @@ bool KItemListController::dragLeaveEvent(QGraphicsSceneDragDropEvent* event, con bool KItemListController::dragMoveEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform) { - Q_UNUSED(event); Q_UNUSED(transform); + if (!m_model || !m_view) { + return false; + } + + KItemListWidget* oldHoveredWidget = hoveredWidget(); + KItemListWidget* newHoveredWidget = widgetForPos(event->pos()); + if (oldHoveredWidget != newHoveredWidget) { + if (oldHoveredWidget) { + oldHoveredWidget->setHovered(false); + emit itemUnhovered(oldHoveredWidget->index()); + } + + if (newHoveredWidget) { + const int index = newHoveredWidget->index(); + if (m_model->supportsDropping(index)) { + newHoveredWidget->setHovered(true); + } + emit itemHovered(index); + } + } + return false; } bool KItemListController::dropEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform) { - Q_UNUSED(event); - Q_UNUSED(transform); + Q_UNUSED(transform) + if (!m_view) { + return false; + } - m_dragging = false; - return false; + const QPointF pos = transform.map(event->pos()); + const int index = m_view->itemAt(pos); + emit itemDropEvent(index, event); + + return true; } bool KItemListController::hoverEnterEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform) @@ -458,46 +530,22 @@ bool KItemListController::hoverEnterEvent(QGraphicsSceneHoverEvent* event, const bool KItemListController::hoverMoveEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform) { - // The implementation assumes that only one item can get hovered no matter - // whether they overlap or not. - Q_UNUSED(transform); if (!m_model || !m_view) { return false; } - // Search the previously hovered item that might get unhovered - KItemListWidget* unhoveredWidget = 0; - foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) { - if (widget->isHovered()) { - unhoveredWidget = widget; - break; + KItemListWidget* oldHoveredWidget = hoveredWidget(); + KItemListWidget* newHoveredWidget = widgetForPos(event->pos()); + if (oldHoveredWidget != newHoveredWidget) { + if (oldHoveredWidget) { + oldHoveredWidget->setHovered(false); + emit itemUnhovered(oldHoveredWidget->index()); } - } - - // Search the currently hovered item - KItemListWidget* hoveredWidget = 0; - foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) { - const QPointF mappedPos = widget->mapFromItem(m_view, event->pos()); - const bool hovered = widget->contains(mappedPos) && - !widget->expansionToggleRect().contains(mappedPos) && - !widget->selectionToggleRect().contains(mappedPos); - if (hovered) { - hoveredWidget = widget; - break; - } - } - - if (unhoveredWidget != hoveredWidget) { - if (unhoveredWidget) { - unhoveredWidget->setHovered(false); - emit itemUnhovered(unhoveredWidget->index()); - } - - if (hoveredWidget) { - hoveredWidget->setHovered(true); - emit itemHovered(hoveredWidget->index()); + if (newHoveredWidget) { + newHoveredWidget->setHovered(true); + emit itemHovered(newHoveredWidget->index()); } } @@ -675,19 +723,28 @@ void KItemListController::slotRubberBandChanged() } } while (!selectionFinished); - m_selectionManager->setSelectedItems(selectedItems + m_oldSelection); + if (QApplication::keyboardModifiers() & Qt::ControlModifier) { + // If Control is pressed, the selection state of all items in the rubberband is toggled. + // Therefore, the new selection contains: + // 1. All previously selected items which are not inside the rubberband, and + // 2. all items inside the rubberband which have not been selected previously. + m_selectionManager->setSelectedItems((m_oldSelection - selectedItems) + (selectedItems - m_oldSelection)); + } + else { + m_selectionManager->setSelectedItems(selectedItems + m_oldSelection); + } } -bool KItemListController::startDragging() +void KItemListController::startDragging() { if (!m_view || !m_model) { - return false; + return; } const QSet selectedItems = m_selectionManager->selectedItems(); QMimeData* data = m_model->createMimeData(selectedItems); if (!data) { - return false; + return; } // The created drag object will be owned and deleted @@ -699,7 +756,37 @@ bool KItemListController::startDragging() drag->setPixmap(pixmap); drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction, Qt::IgnoreAction); - return true; +} + +KItemListWidget* KItemListController::hoveredWidget() const +{ + Q_ASSERT(m_view); + + foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) { + if (widget->isHovered()) { + return widget; + } + } + + return 0; +} + +KItemListWidget* KItemListController::widgetForPos(const QPointF& pos) const +{ + Q_ASSERT(m_view); + + foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) { + const QPointF mappedPos = widget->mapFromItem(m_view, pos); + + const bool hovered = widget->contains(mappedPos) && + !widget->expansionToggleRect().contains(mappedPos) && + !widget->selectionToggleRect().contains(mappedPos); + if (hovered) { + return widget; + } + } + + return 0; } #include "kitemlistcontroller.moc"