]> cloud.milkyroute.net Git - dolphin.git/blob - src/kitemviews/kitemlistcontroller.cpp
Added support for highlighting items by typing their name on the keyboard.
[dolphin.git] / src / kitemviews / kitemlistcontroller.cpp
1 /***************************************************************************
2 * Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com> *
3 * *
4 * Based on the Itemviews NG project from Trolltech Labs: *
5 * http://qt.gitorious.org/qt-labs/itemviews-ng *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
21 ***************************************************************************/
22
23 #include "kitemlistcontroller.h"
24
25 #include "kitemlistview.h"
26 #include "kitemlistrubberband_p.h"
27 #include "kitemlistselectionmanager.h"
28 #include "kitemlistkeyboardsearchmanager_p.h"
29
30 #include <QApplication>
31 #include <QDrag>
32 #include <QEvent>
33 #include <QGraphicsSceneEvent>
34 #include <QMimeData>
35
36 #include <KGlobalSettings>
37 #include <KDebug>
38
39 KItemListController::KItemListController(QObject* parent) :
40 QObject(parent),
41 m_dragging(false),
42 m_selectionBehavior(NoSelection),
43 m_model(0),
44 m_view(0),
45 m_selectionManager(new KItemListSelectionManager(this)),
46 m_keyboardManager(new KItemListKeyboardSearchManager(this)),
47 m_pressedIndex(-1),
48 m_pressedMousePos(),
49 m_oldSelection()
50 {
51 connect(m_keyboardManager, SIGNAL(requestItemActivation(QString,bool)), this, SLOT(slotKeyboardActivationRequested(QString,bool)));
52 }
53
54 KItemListController::~KItemListController()
55 {
56 }
57
58 void KItemListController::setModel(KItemModelBase* model)
59 {
60 if (m_model == model) {
61 return;
62 }
63
64 KItemModelBase* oldModel = m_model;
65 m_model = model;
66
67 if (m_view) {
68 m_view->setModel(m_model);
69 }
70
71 m_selectionManager->setModel(m_model);
72
73 emit modelChanged(m_model, oldModel);
74 }
75
76 KItemModelBase* KItemListController::model() const
77 {
78 return m_model;
79 }
80
81 KItemListSelectionManager* KItemListController::selectionManager() const
82 {
83 return m_selectionManager;
84 }
85
86 void KItemListController::setView(KItemListView* view)
87 {
88 if (m_view == view) {
89 return;
90 }
91
92 KItemListView* oldView = m_view;
93 if (oldView) {
94 disconnect(oldView, SIGNAL(offsetChanged(qreal,qreal)), this, SLOT(slotViewOffsetChanged(qreal,qreal)));
95 }
96
97 m_view = view;
98
99 if (m_view) {
100 m_view->setController(this);
101 m_view->setModel(m_model);
102 connect(m_view, SIGNAL(offsetChanged(qreal,qreal)), this, SLOT(slotViewOffsetChanged(qreal,qreal)));
103 }
104
105 emit viewChanged(m_view, oldView);
106 }
107
108 KItemListView* KItemListController::view() const
109 {
110 return m_view;
111 }
112
113 void KItemListController::setSelectionBehavior(SelectionBehavior behavior)
114 {
115 m_selectionBehavior = behavior;
116 }
117
118 KItemListController::SelectionBehavior KItemListController::selectionBehavior() const
119 {
120 return m_selectionBehavior;
121 }
122
123 bool KItemListController::showEvent(QShowEvent* event)
124 {
125 Q_UNUSED(event);
126 return false;
127 }
128
129 bool KItemListController::hideEvent(QHideEvent* event)
130 {
131 Q_UNUSED(event);
132 return false;
133 }
134
135 bool KItemListController::keyPressEvent(QKeyEvent* event)
136 {
137 const bool shiftPressed = event->modifiers() & Qt::ShiftModifier;
138 const bool controlPressed = event->modifiers() & Qt::ControlModifier;
139 const bool shiftOrControlPressed = shiftPressed || controlPressed;
140
141 int index = m_selectionManager->currentItem();
142 const int itemCount = m_model->count();
143 const int itemsPerRow = m_view->itemsPerOffset();
144
145 // For horizontal scroll orientation, transform
146 // the arrow keys to simplify the event handling.
147 int key = event->key();
148 if (m_view->scrollOrientation() == Qt::Horizontal) {
149 switch (key) {
150 case Qt::Key_Up: key = Qt::Key_Left; break;
151 case Qt::Key_Down: key = Qt::Key_Right; break;
152 case Qt::Key_Left: key = Qt::Key_Up; break;
153 case Qt::Key_Right: key = Qt::Key_Down; break;
154 default: break;
155 }
156 }
157
158 switch (key) {
159 case Qt::Key_Home:
160 index = 0;
161 break;
162
163 case Qt::Key_End:
164 index = itemCount - 1;
165 break;
166
167 case Qt::Key_Left:
168 if (index > 0) {
169 index--;
170 }
171 break;
172
173 case Qt::Key_Right:
174 if (index < itemCount - 1) {
175 index++;
176 }
177 break;
178
179 case Qt::Key_Up:
180 if (index >= itemsPerRow) {
181 index -= itemsPerRow;
182 }
183 break;
184
185 case Qt::Key_Down:
186 if (index + itemsPerRow < itemCount) {
187 // We are not in the last row yet.
188 index += itemsPerRow;
189 }
190 else {
191 // We are either in the last row already, or we are in the second-last row,
192 // and there is no item below the current item.
193 // In the latter case, we jump to the very last item.
194 const int currentColumn = index % itemsPerRow;
195 const int lastItemColumn = (itemCount - 1) % itemsPerRow;
196 const bool inLastRow = currentColumn < lastItemColumn;
197 if (!inLastRow) {
198 index = itemCount - 1;
199 }
200 }
201 break;
202
203 case Qt::Key_Space:
204 if (controlPressed) {
205 m_selectionManager->endAnchoredSelection();
206 m_selectionManager->setSelected(index, 1, KItemListSelectionManager::Toggle);
207 m_selectionManager->beginAnchoredSelection(index);
208 break;
209 }
210
211 default:
212 m_keyboardManager->addKeys(event->text());
213 return false;
214 }
215
216 if (m_selectionManager->currentItem() != index) {
217 if (controlPressed) {
218 m_selectionManager->endAnchoredSelection();
219 }
220
221 m_selectionManager->setCurrentItem(index);
222
223 if (!shiftOrControlPressed || m_selectionBehavior == SingleSelection) {
224 m_selectionManager->clearSelection();
225 m_selectionManager->setSelected(index, 1);
226 }
227
228 if (!shiftPressed) {
229 m_selectionManager->beginAnchoredSelection(index);
230 }
231 }
232 return true;
233 }
234
235 void KItemListController::slotKeyboardActivationRequested(const QString& text, bool searchFromNextItem)
236 {
237 if (!m_model) {
238 return;
239 }
240 const int currentIndex = m_selectionManager->currentItem();
241 int index;
242 if (searchFromNextItem) {
243 index = m_model->indexForKeyboardSearch(text, (currentIndex + 1) % m_model->count());
244 }
245 else {
246 index = m_model->indexForKeyboardSearch(text, currentIndex);
247 }
248 if (index >= 0) {
249 m_selectionManager->setCurrentItem(index);
250 m_selectionManager->clearSelection();
251 m_selectionManager->setSelected(index, 1);
252 m_selectionManager->beginAnchoredSelection(index);
253 }
254 }
255
256 bool KItemListController::inputMethodEvent(QInputMethodEvent* event)
257 {
258 Q_UNUSED(event);
259 return false;
260 }
261
262 bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform)
263 {
264 if (!m_view) {
265 return false;
266 }
267
268 m_dragging = false;
269 m_pressedMousePos = transform.map(event->pos());
270 m_pressedIndex = m_view->itemAt(m_pressedMousePos);
271
272 if (m_view->isAboveExpansionToggle(m_pressedIndex, m_pressedMousePos)) {
273 m_selectionManager->setCurrentItem(m_pressedIndex);
274 return true;
275 }
276
277 const bool shiftPressed = event->modifiers() & Qt::ShiftModifier;
278 const bool controlPressed = event->modifiers() & Qt::ControlModifier;
279
280 if (m_selectionBehavior == SingleSelection) {
281 m_selectionManager->clearSelection();
282 }
283
284 if (!shiftPressed) {
285 // Finish the anchored selection before the current index is changed
286 m_selectionManager->endAnchoredSelection();
287 }
288
289 if (m_pressedIndex >= 0) {
290 m_selectionManager->setCurrentItem(m_pressedIndex);
291
292 switch (m_selectionBehavior) {
293 case NoSelection:
294 break;
295
296 case SingleSelection:
297 m_selectionManager->setSelected(m_pressedIndex);
298 break;
299
300 case MultiSelection:
301 if (controlPressed) {
302 m_selectionManager->setSelected(m_pressedIndex, 1, KItemListSelectionManager::Toggle);
303 m_selectionManager->beginAnchoredSelection(m_pressedIndex);
304 } else if (!shiftPressed || !m_selectionManager->isAnchoredSelectionActive()) {
305 // Select the pressed item and start a new anchored selection
306 m_selectionManager->setSelected(m_pressedIndex, 1, KItemListSelectionManager::Select);
307 m_selectionManager->beginAnchoredSelection(m_pressedIndex);
308 }
309 break;
310
311 default:
312 Q_ASSERT(false);
313 break;
314 }
315
316 return true;
317 } else {
318 KItemListRubberBand* rubberBand = m_view->rubberBand();
319 QPointF startPos = m_pressedMousePos;
320 if (m_view->scrollOrientation() == Qt::Vertical) {
321 startPos.ry() += m_view->offset();
322 if (m_view->itemSize().width() < 0) {
323 // Use a special rubberband for views that have only one column and
324 // expand the rubberband to use the whole width of the view.
325 startPos.setX(0);
326 }
327 } else {
328 startPos.rx() += m_view->offset();
329 }
330
331 m_oldSelection = m_selectionManager->selectedItems();
332 rubberBand->setStartPosition(startPos);
333 rubberBand->setEndPosition(startPos);
334 rubberBand->setActive(true);
335 connect(rubberBand, SIGNAL(endPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandChanged()));
336 m_view->setAutoScroll(true);
337 }
338
339 return false;
340 }
341
342 bool KItemListController::mouseMoveEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform)
343 {
344 if (!m_view) {
345 return false;
346 }
347
348 if (m_pressedIndex >= 0) {
349 // Check whether a dragging should be started
350 if (!m_dragging && (event->buttons() & Qt::LeftButton)) {
351 const QPointF pos = transform.map(event->pos());
352 const qreal minDragDiff = 4;
353 const bool hasMinDragDiff = qAbs(pos.x() - m_pressedMousePos.x()) >= minDragDiff ||
354 qAbs(pos.y() - m_pressedMousePos.y()) >= minDragDiff;
355 if (hasMinDragDiff && startDragging()) {
356 m_dragging = true;
357 }
358 }
359 } else {
360 KItemListRubberBand* rubberBand = m_view->rubberBand();
361 if (rubberBand->isActive()) {
362 QPointF endPos = transform.map(event->pos());
363 if (m_view->scrollOrientation() == Qt::Vertical) {
364 endPos.ry() += m_view->offset();
365 if (m_view->itemSize().width() < 0) {
366 // Use a special rubberband for views that have only one column and
367 // expand the rubberband to use the whole width of the view.
368 endPos.setX(m_view->size().width());
369 }
370 } else {
371 endPos.rx() += m_view->offset();
372 }
373 rubberBand->setEndPosition(endPos);
374 }
375 }
376
377 return false;
378 }
379
380 bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform)
381 {
382 if (!m_view) {
383 return false;
384 }
385
386 const bool shiftOrControlPressed = event->modifiers() & Qt::ShiftModifier ||
387 event->modifiers() & Qt::ControlModifier;
388
389 bool clearSelection = !shiftOrControlPressed && !m_dragging && !(event->button() == Qt::RightButton);
390
391 KItemListRubberBand* rubberBand = m_view->rubberBand();
392 if (rubberBand->isActive()) {
393 disconnect(rubberBand, SIGNAL(endPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandChanged()));
394 rubberBand->setActive(false);
395 m_oldSelection.clear();
396 m_view->setAutoScroll(false);
397
398 if (rubberBand->startPosition() != rubberBand->endPosition()) {
399 clearSelection = false;
400 }
401 }
402
403 const QPointF pos = transform.map(event->pos());
404 const int index = m_view->itemAt(pos);
405
406 if (index >= 0 && index == m_pressedIndex) {
407 // The release event is done above the same item as the press event
408
409 if (clearSelection) {
410 // Clear the previous selection but reselect the current index
411 m_selectionManager->setSelectedItems(QSet<int>() << index);
412 }
413
414 bool emitItemClicked = true;
415 if (event->button() & Qt::LeftButton) {
416 if (m_view->isAboveExpansionToggle(index, pos)) {
417 emit itemExpansionToggleClicked(index);
418 emitItemClicked = false;
419 } else if (shiftOrControlPressed || !KGlobalSettings::singleClick()) {
420 emitItemClicked = false;
421 }
422 }
423
424 if (emitItemClicked) {
425 emit itemClicked(index, event->button());
426 }
427 } else if (clearSelection) {
428 m_selectionManager->clearSelection();
429 }
430
431 m_dragging = false;
432 m_pressedMousePos = QPointF();
433 m_pressedIndex = -1;
434 return false;
435 }
436
437 bool KItemListController::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform)
438 {
439 const QPointF pos = transform.map(event->pos());
440 const int index = m_view->itemAt(pos);
441
442 bool emitItemClicked = !KGlobalSettings::singleClick() &&
443 (event->button() & Qt::LeftButton) &&
444 index >= 0 && index < m_model->count();
445 if (emitItemClicked) {
446 emit itemClicked(index, event->button());
447 }
448 return false;
449 }
450
451 bool KItemListController::dragEnterEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform)
452 {
453 Q_UNUSED(event);
454 Q_UNUSED(transform);
455 return false;
456 }
457
458 bool KItemListController::dragLeaveEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform)
459 {
460 Q_UNUSED(event);
461 Q_UNUSED(transform);
462 return false;
463 }
464
465 bool KItemListController::dragMoveEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform)
466 {
467 Q_UNUSED(event);
468 Q_UNUSED(transform);
469 return false;
470 }
471
472 bool KItemListController::dropEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform)
473 {
474 Q_UNUSED(event);
475 Q_UNUSED(transform);
476
477 m_dragging = false;
478 return false;
479 }
480
481 bool KItemListController::hoverEnterEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform)
482 {
483 Q_UNUSED(event);
484 Q_UNUSED(transform);
485 return false;
486 }
487
488 bool KItemListController::hoverMoveEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform)
489 {
490 // The implementation assumes that only one item can get hovered no matter
491 // whether they overlap or not.
492
493 Q_UNUSED(transform);
494 if (!m_model || !m_view) {
495 return false;
496 }
497
498 // Search the previously hovered item that might get unhovered
499 KItemListWidget* unhoveredWidget = 0;
500 foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) {
501 if (widget->isHovered()) {
502 unhoveredWidget = widget;
503 break;
504 }
505 }
506
507 // Search the currently hovered item
508 KItemListWidget* hoveredWidget = 0;
509 foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) {
510 const QPointF mappedPos = widget->mapFromItem(m_view, event->pos());
511
512 const bool hovered = widget->contains(mappedPos) &&
513 !widget->expansionToggleRect().contains(mappedPos) &&
514 !widget->selectionToggleRect().contains(mappedPos);
515 if (hovered) {
516 hoveredWidget = widget;
517 break;
518 }
519 }
520
521 if (unhoveredWidget != hoveredWidget) {
522 if (unhoveredWidget) {
523 unhoveredWidget->setHovered(false);
524 emit itemUnhovered(unhoveredWidget->index());
525 }
526
527 if (hoveredWidget) {
528 hoveredWidget->setHovered(true);
529 emit itemHovered(hoveredWidget->index());
530 }
531 }
532
533 return false;
534 }
535
536 bool KItemListController::hoverLeaveEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform)
537 {
538 Q_UNUSED(event);
539 Q_UNUSED(transform);
540
541 if (!m_model || !m_view) {
542 return false;
543 }
544
545 foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) {
546 if (widget->isHovered()) {
547 widget->setHovered(false);
548 emit itemUnhovered(widget->index());
549 }
550 }
551 return false;
552 }
553
554 bool KItemListController::wheelEvent(QGraphicsSceneWheelEvent* event, const QTransform& transform)
555 {
556 Q_UNUSED(event);
557 Q_UNUSED(transform);
558 return false;
559 }
560
561 bool KItemListController::resizeEvent(QGraphicsSceneResizeEvent* event, const QTransform& transform)
562 {
563 Q_UNUSED(event);
564 Q_UNUSED(transform);
565 return false;
566 }
567
568 bool KItemListController::processEvent(QEvent* event, const QTransform& transform)
569 {
570 if (!event) {
571 return false;
572 }
573
574 switch (event->type()) {
575 case QEvent::KeyPress:
576 return keyPressEvent(static_cast<QKeyEvent*>(event));
577 case QEvent::InputMethod:
578 return inputMethodEvent(static_cast<QInputMethodEvent*>(event));
579 case QEvent::GraphicsSceneMousePress:
580 return mousePressEvent(static_cast<QGraphicsSceneMouseEvent*>(event), QTransform());
581 case QEvent::GraphicsSceneMouseMove:
582 return mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent*>(event), QTransform());
583 case QEvent::GraphicsSceneMouseRelease:
584 return mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent*>(event), QTransform());
585 case QEvent::GraphicsSceneMouseDoubleClick:
586 return mouseDoubleClickEvent(static_cast<QGraphicsSceneMouseEvent*>(event), QTransform());
587 case QEvent::GraphicsSceneWheel:
588 return wheelEvent(static_cast<QGraphicsSceneWheelEvent*>(event), QTransform());
589 case QEvent::GraphicsSceneDragEnter:
590 return dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent*>(event), QTransform());
591 case QEvent::GraphicsSceneDragLeave:
592 return dragLeaveEvent(static_cast<QGraphicsSceneDragDropEvent*>(event), QTransform());
593 case QEvent::GraphicsSceneDragMove:
594 return dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent*>(event), QTransform());
595 case QEvent::GraphicsSceneDrop:
596 return dropEvent(static_cast<QGraphicsSceneDragDropEvent*>(event), QTransform());
597 case QEvent::GraphicsSceneHoverEnter:
598 return hoverEnterEvent(static_cast<QGraphicsSceneHoverEvent*>(event), QTransform());
599 case QEvent::GraphicsSceneHoverMove:
600 return hoverMoveEvent(static_cast<QGraphicsSceneHoverEvent*>(event), QTransform());
601 case QEvent::GraphicsSceneHoverLeave:
602 return hoverLeaveEvent(static_cast<QGraphicsSceneHoverEvent*>(event), QTransform());
603 case QEvent::GraphicsSceneResize:
604 return resizeEvent(static_cast<QGraphicsSceneResizeEvent*>(event), transform);
605 default:
606 break;
607 }
608
609 return false;
610 }
611
612 void KItemListController::slotViewOffsetChanged(qreal current, qreal previous)
613 {
614 if (!m_view) {
615 return;
616 }
617
618 KItemListRubberBand* rubberBand = m_view->rubberBand();
619 if (rubberBand->isActive()) {
620 const qreal diff = current - previous;
621 // TODO: Ideally just QCursor::pos() should be used as
622 // new end-position but it seems there is no easy way
623 // to have something like QWidget::mapFromGlobal() for QGraphicsWidget
624 // (... or I just missed an easy way to do the mapping)
625 QPointF endPos = rubberBand->endPosition();
626 if (m_view->scrollOrientation() == Qt::Vertical) {
627 endPos.ry() += diff;
628 } else {
629 endPos.rx() += diff;
630 }
631
632 rubberBand->setEndPosition(endPos);
633 }
634 }
635
636 void KItemListController::slotRubberBandChanged()
637 {
638 if (!m_view || !m_model || m_model->count() <= 0) {
639 return;
640 }
641
642 const KItemListRubberBand* rubberBand = m_view->rubberBand();
643 const QPointF startPos = rubberBand->startPosition();
644 const QPointF endPos = rubberBand->endPosition();
645 QRectF rubberBandRect = QRectF(startPos, endPos).normalized();
646
647 const bool scrollVertical = (m_view->scrollOrientation() == Qt::Vertical);
648 if (scrollVertical) {
649 rubberBandRect.translate(0, -m_view->offset());
650 } else {
651 rubberBandRect.translate(-m_view->offset(), 0);
652 }
653
654 if (!m_oldSelection.isEmpty()) {
655 // Clear the old selection that was available before the rubberband has
656 // been activated in case if no Shift- or Control-key are pressed
657 const bool shiftOrControlPressed = QApplication::keyboardModifiers() & Qt::ShiftModifier ||
658 QApplication::keyboardModifiers() & Qt::ControlModifier;
659 if (!shiftOrControlPressed) {
660 m_oldSelection.clear();
661 }
662 }
663
664 QSet<int> selectedItems;
665
666 // Select all visible items that intersect with the rubberband
667 foreach (const KItemListWidget* widget, m_view->visibleItemListWidgets()) {
668 const int index = widget->index();
669
670 const QRectF widgetRect = m_view->itemBoundingRect(index);
671 if (widgetRect.intersects(rubberBandRect)) {
672 const QRectF iconRect = widget->iconBoundingRect().translated(widgetRect.topLeft());
673 const QRectF textRect = widget->textBoundingRect().translated(widgetRect.topLeft());
674 if (iconRect.intersects(rubberBandRect) || textRect.intersects(rubberBandRect)) {
675 selectedItems.insert(index);
676 }
677 }
678 }
679
680 // Select all invisible items that intersect with the rubberband. Instead of
681 // iterating all items only the area which might be touched by the rubberband
682 // will be checked.
683 const bool increaseIndex = scrollVertical ?
684 startPos.y() > endPos.y(): startPos.x() > endPos.x();
685
686 int index = increaseIndex ? m_view->lastVisibleIndex() + 1 : m_view->firstVisibleIndex() - 1;
687 bool selectionFinished = false;
688 do {
689 const QRectF widgetRect = m_view->itemBoundingRect(index);
690 if (widgetRect.intersects(rubberBandRect)) {
691 selectedItems.insert(index);
692 }
693
694 if (increaseIndex) {
695 ++index;
696 selectionFinished = (index >= m_model->count()) ||
697 ( scrollVertical && widgetRect.top() > rubberBandRect.bottom()) ||
698 (!scrollVertical && widgetRect.left() > rubberBandRect.right());
699 } else {
700 --index;
701 selectionFinished = (index < 0) ||
702 ( scrollVertical && widgetRect.bottom() < rubberBandRect.top()) ||
703 (!scrollVertical && widgetRect.right() < rubberBandRect.left());
704 }
705 } while (!selectionFinished);
706
707 if (QApplication::keyboardModifiers() & Qt::ControlModifier) {
708 // If Control is pressed, the selection state of all items in the rubberband is toggled.
709 // Therefore, the new selection contains:
710 // 1. All previously selected items which are not inside the rubberband, and
711 // 2. all items inside the rubberband which have not been selected previously.
712 m_selectionManager->setSelectedItems((m_oldSelection - selectedItems) + (selectedItems - m_oldSelection));
713 }
714 else {
715 m_selectionManager->setSelectedItems(selectedItems + m_oldSelection);
716 }
717 }
718
719 bool KItemListController::startDragging()
720 {
721 if (!m_view || !m_model) {
722 return false;
723 }
724
725 const QSet<int> selectedItems = m_selectionManager->selectedItems();
726 QMimeData* data = m_model->createMimeData(selectedItems);
727 if (!data) {
728 return false;
729 }
730
731 // The created drag object will be owned and deleted
732 // by QApplication::activeWindow().
733 QDrag* drag = new QDrag(QApplication::activeWindow());
734 drag->setMimeData(data);
735
736 const QPixmap pixmap = m_view->createDragPixmap(selectedItems);
737 drag->setPixmap(pixmap);
738
739 drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction, Qt::IgnoreAction);
740 return true;
741 }
742
743 #include "kitemlistcontroller.moc"