+ 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);
+ }
+ else {
+ m_selectionManager->setSelectedItems(selectedItems + m_oldSelection);
+ }
+}
+
+void KItemListController::startDragging()
+{
+ if (!m_view || !m_model) {
+ return;
+ }
+
+ const KItemSet selectedItems = m_selectionManager->selectedItems();
+ if (selectedItems.isEmpty()) {
+ return;
+ }
+
+ 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);
+
+ const QPoint hotSpot((pixmap.width() / pixmap.devicePixelRatio()) / 2, 0);
+ drag->setHotSpot(hotSpot);
+
+ drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction, Qt::MoveAction);
+
+ QAccessibleEvent accessibilityEvent(view(), QAccessible::DragDropStart);
+ QAccessible::updateAccessibility(&accessibilityEvent);
+}
+
+KItemListWidget* KItemListController::hoveredWidget() const
+{
+ Q_ASSERT(m_view);
+
+ foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) {
+ if (widget->isHovered()) {
+ return widget;
+ }
+ }
+
+ return nullptr;
+}
+
+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);
+ if (hovered) {
+ return widget;
+ }
+ }
+
+ return nullptr;
+}
+
+void KItemListController::updateKeyboardAnchor()
+{
+ const bool validAnchor = m_keyboardAnchorIndex >= 0 &&
+ m_keyboardAnchorIndex < m_model->count() &&
+ keyboardAnchorPos(m_keyboardAnchorIndex) == m_keyboardAnchorPos;
+ if (!validAnchor) {
+ const int index = m_selectionManager->currentItem();
+ m_keyboardAnchorIndex = index;
+ m_keyboardAnchorPos = keyboardAnchorPos(index);
+ }
+}
+
+int KItemListController::nextRowIndex(int index) const
+{
+ if (m_keyboardAnchorIndex < 0) {
+ return index;
+ }
+
+ const int maxIndex = m_model->count() - 1;
+ if (index == maxIndex) {
+ return index;
+ }
+
+ // Calculate the index of the last column inside the row of the current index
+ int lastColumnIndex = index;
+ while (keyboardAnchorPos(lastColumnIndex + 1) > keyboardAnchorPos(lastColumnIndex)) {
+ ++lastColumnIndex;
+ if (lastColumnIndex >= maxIndex) {
+ return index;
+ }
+ }
+
+ // Based on the last column index go to the next row and calculate the nearest index
+ // that is below the current index
+ int nextRowIndex = lastColumnIndex + 1;
+ int searchIndex = nextRowIndex;
+ qreal minDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(nextRowIndex));
+ while (searchIndex < maxIndex && keyboardAnchorPos(searchIndex + 1) > keyboardAnchorPos(searchIndex)) {
+ ++searchIndex;
+ const qreal searchDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(searchIndex));
+ if (searchDiff < minDiff) {
+ minDiff = searchDiff;
+ nextRowIndex = searchIndex;
+ }
+ }
+
+ return nextRowIndex;
+}
+
+int KItemListController::previousRowIndex(int index) const
+{
+ if (m_keyboardAnchorIndex < 0 || index == 0) {
+ return index;
+ }
+
+ // Calculate the index of the first column inside the row of the current index
+ int firstColumnIndex = index;
+ while (keyboardAnchorPos(firstColumnIndex - 1) < keyboardAnchorPos(firstColumnIndex)) {
+ --firstColumnIndex;
+ if (firstColumnIndex <= 0) {
+ return index;
+ }
+ }
+
+ // Based on the first column index go to the previous row and calculate the nearest index
+ // that is above the current index
+ int previousRowIndex = firstColumnIndex - 1;
+ int searchIndex = previousRowIndex;
+ qreal minDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(previousRowIndex));
+ while (searchIndex > 0 && keyboardAnchorPos(searchIndex - 1) < keyboardAnchorPos(searchIndex)) {
+ --searchIndex;
+ const qreal searchDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(searchIndex));
+ if (searchDiff < minDiff) {
+ minDiff = searchDiff;
+ previousRowIndex = searchIndex;
+ }
+ }
+
+ return previousRowIndex;
+}
+
+qreal KItemListController::keyboardAnchorPos(int index) const
+{
+ const QRectF itemRect = m_view->itemRect(index);
+ if (!itemRect.isEmpty()) {
+ return (m_view->scrollOrientation() == Qt::Vertical) ? itemRect.x() : itemRect.y();
+ }
+
+ return 0;
+}
+
+void KItemListController::updateExtendedSelectionRegion()
+{
+ if (m_view) {
+ const bool extend = (m_selectionBehavior != MultiSelection);
+ KItemListStyleOption option = m_view->styleOption();
+ if (option.extendedSelectionRegion != extend) {
+ option.extendedSelectionRegion = extend;
+ m_view->setStyleOption(option);
+ }
+ }