X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/2f0ceedae088158b8af24a5e94500a7d1c0edecb..d2a3510cc372685ad491a0b653587bf569a132aa:/src/kitemviews/kitemlistcontroller.cpp diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp index 92a14b23d..025249a34 100644 --- a/src/kitemviews/kitemlistcontroller.cpp +++ b/src/kitemviews/kitemlistcontroller.cpp @@ -25,11 +25,15 @@ #include "kitemlistview.h" #include "kitemlistrubberband_p.h" #include "kitemlistselectionmanager.h" +#include "kitemlistkeyboardsearchmanager_p.h" #include +#include #include #include +#include +#include #include KItemListController::KItemListController(QObject* parent) : @@ -38,8 +42,13 @@ KItemListController::KItemListController(QObject* parent) : m_model(0), m_view(0), m_selectionManager(new KItemListSelectionManager(this)), - m_pressedIndex(-1) + 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() @@ -191,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) { @@ -221,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); @@ -233,18 +270,18 @@ bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const return false; } - const QPointF pos = transform.map(event->pos()); - m_pressedIndex = m_view->itemAt(pos); + m_pressedMousePos = transform.map(event->pos()); + m_pressedIndex = m_view->itemAt(m_pressedMousePos); - if (m_view->isAboveExpansionToggle(m_pressedIndex, pos)) { + if (m_view->isAboveExpansionToggle(m_pressedIndex, m_pressedMousePos)) { + m_selectionManager->setCurrentItem(m_pressedIndex); return true; } const bool shiftPressed = event->modifiers() & Qt::ShiftModifier; const bool controlPressed = event->modifiers() & Qt::ControlModifier; - const bool shiftOrControlPressed = shiftPressed || controlPressed; - if (!shiftOrControlPressed || m_selectionBehavior == SingleSelection) { + if (m_selectionBehavior == SingleSelection) { m_selectionManager->clearSelection(); } @@ -268,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); @@ -282,8 +324,12 @@ bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const return true; } else { + if (event->buttons() & Qt::RightButton) { + m_selectionManager->clearSelection(); + } + KItemListRubberBand* rubberBand = m_view->rubberBand(); - QPointF startPos = pos; + QPointF startPos = m_pressedMousePos; if (m_view->scrollOrientation() == Qt::Vertical) { startPos.ry() += m_view->offset(); if (m_view->itemSize().width() < 0) { @@ -294,10 +340,13 @@ bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const } else { startPos.rx() += m_view->offset(); } + + m_oldSelection = m_selectionManager->selectedItems(); rubberBand->setStartPosition(startPos); rubberBand->setEndPosition(startPos); rubberBand->setActive(true); connect(rubberBand, SIGNAL(endPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandChanged())); + m_view->setAutoScroll(true); } return false; @@ -309,20 +358,33 @@ bool KItemListController::mouseMoveEvent(QGraphicsSceneMouseEvent* event, const return false; } - KItemListRubberBand* rubberBand = m_view->rubberBand(); - if (rubberBand->isActive()) { - QPointF endPos = transform.map(event->pos()); - if (m_view->scrollOrientation() == Qt::Vertical) { - endPos.ry() += m_view->offset(); - if (m_view->itemSize().width() < 0) { - // Use a special rubberband for views that have only one column and - // expand the rubberband to use the whole width of the view. - endPos.setX(m_view->size().width()); + if (m_pressedIndex >= 0) { + // Check whether a dragging should be started + 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(); } - } else { - endPos.rx() += m_view->offset(); } - rubberBand->setEndPosition(endPos); + } else { + KItemListRubberBand* rubberBand = m_view->rubberBand(); + if (rubberBand->isActive()) { + QPointF endPos = transform.map(event->pos()); + if (m_view->scrollOrientation() == Qt::Vertical) { + endPos.ry() += m_view->offset(); + if (m_view->itemSize().width() < 0) { + // Use a special rubberband for views that have only one column and + // expand the rubberband to use the whole width of the view. + endPos.setX(m_view->size().width()); + } + } else { + endPos.rx() += m_view->offset(); + } + rubberBand->setEndPosition(endPos); + } } return false; @@ -334,47 +396,73 @@ bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, con return false; } + const bool shiftOrControlPressed = event->modifiers() & Qt::ShiftModifier || + event->modifiers() & Qt::ControlModifier; + + 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_pressedIndex = -1; - return false; + m_oldSelection.clear(); + m_view->setAutoScroll(false); + + if (rubberBand->startPosition() != rubberBand->endPosition()) { + clearSelection = false; + } } const QPointF pos = transform.map(event->pos()); const int index = m_view->itemAt(pos); - const bool shiftOrControlPressed = event->modifiers() & Qt::ShiftModifier || event->modifiers() & Qt::ControlModifier; if (index >= 0 && index == m_pressedIndex) { // The release event is done above the same item as the press event - bool emitItemClicked = true; + + if (clearSelection) { + // Clear the previous selection but reselect the current index + m_selectionManager->setSelectedItems(QSet() << index); + } + if (event->button() & Qt::LeftButton) { + bool emitItemActivated = true; if (m_view->isAboveExpansionToggle(index, pos)) { emit itemExpansionToggleClicked(index); - emitItemClicked = false; - } - else if (shiftOrControlPressed) { + emitItemActivated = false; + } else if (shiftOrControlPressed) { // The mouse click should only update the selection, not trigger the item - emitItemClicked = false; + emitItemActivated = false; + } else if (!KGlobalSettings::singleClick()) { + emitItemActivated = false; } + 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())); } - - if (emitItemClicked) { - emit itemClicked(index, event->button()); - } - } else if (!shiftOrControlPressed) { + } else if (clearSelection) { m_selectionManager->clearSelection(); } + m_pressedMousePos = QPointF(); m_pressedIndex = -1; return false; } bool KItemListController::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform) { - Q_UNUSED(event); - Q_UNUSED(transform); + const QPointF pos = transform.map(event->pos()); + const int index = m_view->itemAt(pos); + + bool emitItemActivated = !KGlobalSettings::singleClick() && + (event->button() & Qt::LeftButton) && + index >= 0 && index < m_model->count(); + if (emitItemActivated) { + emit itemActivated(index); + } return false; } @@ -510,6 +598,8 @@ bool KItemListController::processEvent(QEvent* event, const QTransform& transfor return mouseMoveEvent(static_cast(event), QTransform()); case QEvent::GraphicsSceneMouseRelease: return mouseReleaseEvent(static_cast(event), QTransform()); + case QEvent::GraphicsSceneMouseDoubleClick: + return mouseDoubleClickEvent(static_cast(event), QTransform()); case QEvent::GraphicsSceneWheel: return wheelEvent(static_cast(event), QTransform()); case QEvent::GraphicsSceneDragEnter: @@ -577,14 +667,13 @@ void KItemListController::slotRubberBandChanged() rubberBandRect.translate(-m_view->offset(), 0); } - QSet previousSelectedItems; - if (m_selectionManager->hasSelection()) { - // Don't clear the current selection in case if the user pressed the - // Shift- or Control-key during the rubberband selection + if (!m_oldSelection.isEmpty()) { + // Clear the old selection that was available before the rubberband has + // been activated in case if no Shift- or Control-key are pressed const bool shiftOrControlPressed = QApplication::keyboardModifiers() & Qt::ShiftModifier || QApplication::keyboardModifiers() & Qt::ControlModifier; - if (shiftOrControlPressed) { - previousSelectedItems = m_selectionManager->selectedItems(); + if (!shiftOrControlPressed) { + m_oldSelection.clear(); } } @@ -631,7 +720,39 @@ void KItemListController::slotRubberBandChanged() } } while (!selectionFinished); - m_selectionManager->setSelectedItems(selectedItems + previousSelectedItems); + 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); + } +} + +void KItemListController::startDragging() +{ + if (!m_view || !m_model) { + return; + } + + const QSet selectedItems = m_selectionManager->selectedItems(); + QMimeData* data = m_model->createMimeData(selectedItems); + if (!data) { + return; + } + + // The created drag object will be owned and deleted + // by QApplication::activeWindow(). + QDrag* drag = new QDrag(QApplication::activeWindow()); + drag->setMimeData(data); + + const QPixmap pixmap = m_view->createDragPixmap(selectedItems); + drag->setPixmap(pixmap); + + drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction, Qt::IgnoreAction); } #include "kitemlistcontroller.moc"