1 /***************************************************************************
2 * Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com> *
4 * Based on the Itemviews NG project from Trolltech Labs: *
5 * http://qt.gitorious.org/qt-labs/itemviews-ng *
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. *
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. *
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 ***************************************************************************/
23 #include "kitemlistcontroller.h"
25 #include "kitemlistview.h"
26 #include "kitemlistrubberband_p.h"
27 #include "kitemlistselectionmanager.h"
28 #include "kitemlistkeyboardsearchmanager_p.h"
30 #include <QApplication>
33 #include <QGraphicsSceneEvent>
37 #include <KGlobalSettings>
40 KItemListController::KItemListController(QObject
* parent
) :
42 m_selectionTogglePressed(false),
43 m_selectionBehavior(NoSelection
),
46 m_selectionManager(new KItemListSelectionManager(this)),
47 m_keyboardManager(new KItemListKeyboardSearchManager(this)),
50 m_autoActivationTimer(0),
53 connect(m_keyboardManager
, SIGNAL(changeCurrentItem(QString
,bool)),
54 this, SLOT(slotChangeCurrentItem(QString
,bool)));
56 m_autoActivationTimer
= new QTimer(this);
57 m_autoActivationTimer
->setSingleShot(true);
58 m_autoActivationTimer
->setInterval(-1);
59 connect(m_autoActivationTimer
, SIGNAL(timeout()), this, SLOT(slotAutoActivationTimeout()));
62 KItemListController::~KItemListController()
66 void KItemListController::setModel(KItemModelBase
* model
)
68 if (m_model
== model
) {
72 KItemModelBase
* oldModel
= m_model
;
76 m_view
->setModel(m_model
);
79 m_selectionManager
->setModel(m_model
);
81 emit
modelChanged(m_model
, oldModel
);
84 KItemModelBase
* KItemListController::model() const
89 KItemListSelectionManager
* KItemListController::selectionManager() const
91 return m_selectionManager
;
94 void KItemListController::setView(KItemListView
* view
)
100 KItemListView
* oldView
= m_view
;
102 disconnect(oldView
, SIGNAL(scrollOffsetChanged(qreal
,qreal
)), this, SLOT(slotViewScrollOffsetChanged(qreal
,qreal
)));
108 m_view
->setController(this);
109 m_view
->setModel(m_model
);
110 connect(m_view
, SIGNAL(scrollOffsetChanged(qreal
,qreal
)), this, SLOT(slotViewScrollOffsetChanged(qreal
,qreal
)));
113 emit
viewChanged(m_view
, oldView
);
116 KItemListView
* KItemListController::view() const
121 void KItemListController::setSelectionBehavior(SelectionBehavior behavior
)
123 m_selectionBehavior
= behavior
;
126 KItemListController::SelectionBehavior
KItemListController::selectionBehavior() const
128 return m_selectionBehavior
;
131 void KItemListController::setAutoActivationDelay(int delay
)
133 m_autoActivationTimer
->setInterval(delay
);
136 int KItemListController::autoActivationDelay() const
138 return m_autoActivationTimer
->interval();
141 bool KItemListController::showEvent(QShowEvent
* event
)
147 bool KItemListController::hideEvent(QHideEvent
* event
)
153 bool KItemListController::keyPressEvent(QKeyEvent
* event
)
155 int index
= m_selectionManager
->currentItem();
156 int key
= event
->key();
158 // Handle the expanding/collapsing of items
159 if (m_view
->supportsItemExpanding() && m_model
->isExpandable(index
)) {
160 if (key
== Qt::Key_Right
) {
161 if (m_model
->setExpanded(index
, true)) {
164 } else if (key
== Qt::Key_Left
) {
165 if (m_model
->setExpanded(index
, false)) {
171 const bool shiftPressed
= event
->modifiers() & Qt::ShiftModifier
;
172 const bool controlPressed
= event
->modifiers() & Qt::ControlModifier
;
173 const bool shiftOrControlPressed
= shiftPressed
|| controlPressed
;
175 const int itemCount
= m_model
->count();
176 const int itemsPerRow
= m_view
->itemsPerOffset();
178 // For horizontal scroll orientation, transform
179 // the arrow keys to simplify the event handling.
180 if (m_view
->scrollOrientation() == Qt::Horizontal
) {
182 case Qt::Key_Up
: key
= Qt::Key_Left
; break;
183 case Qt::Key_Down
: key
= Qt::Key_Right
; break;
184 case Qt::Key_Left
: key
= Qt::Key_Up
; break;
185 case Qt::Key_Right
: key
= Qt::Key_Down
; break;
197 index
= itemCount
- 1;
207 if (index
< itemCount
- 1) {
213 if (index
>= itemsPerRow
) {
214 index
-= itemsPerRow
;
219 if (index
+ itemsPerRow
< itemCount
) {
220 // We are not in the last row yet.
221 index
+= itemsPerRow
;
224 // We are either in the last row already, or we are in the second-last row,
225 // and there is no item below the current item.
226 // In the latter case, we jump to the very last item.
227 const int currentColumn
= index
% itemsPerRow
;
228 const int lastItemColumn
= (itemCount
- 1) % itemsPerRow
;
229 const bool inLastRow
= currentColumn
< lastItemColumn
;
231 index
= itemCount
- 1;
237 case Qt::Key_Return
: {
238 const QSet
<int> selectedItems
= m_selectionManager
->selectedItems();
239 if (selectedItems
.count() >= 2) {
240 emit
itemsActivated(selectedItems
);
241 } else if (selectedItems
.count() == 1) {
242 emit
itemActivated(selectedItems
.toList().first());
244 emit
itemActivated(index
);
250 if (controlPressed
) {
251 m_selectionManager
->endAnchoredSelection();
252 m_selectionManager
->setSelected(index
, 1, KItemListSelectionManager::Toggle
);
253 m_selectionManager
->beginAnchoredSelection(index
);
258 m_keyboardManager
->addKeys(event
->text());
262 if (m_selectionManager
->currentItem() != index
) {
263 if (controlPressed
) {
264 m_selectionManager
->endAnchoredSelection();
267 m_selectionManager
->setCurrentItem(index
);
269 if (!shiftOrControlPressed
|| m_selectionBehavior
== SingleSelection
) {
270 m_selectionManager
->clearSelection();
271 m_selectionManager
->setSelected(index
, 1);
275 m_selectionManager
->beginAnchoredSelection(index
);
278 m_view
->scrollToItem(index
);
283 void KItemListController::slotChangeCurrentItem(const QString
& text
, bool searchFromNextItem
)
285 if (!m_model
|| m_model
->count() == 0) {
288 const int currentIndex
= m_selectionManager
->currentItem();
290 if (searchFromNextItem
) {
291 index
= m_model
->indexForKeyboardSearch(text
, (currentIndex
+ 1) % m_model
->count());
294 index
= m_model
->indexForKeyboardSearch(text
, currentIndex
);
297 m_selectionManager
->setCurrentItem(index
);
298 m_selectionManager
->clearSelection();
299 m_selectionManager
->setSelected(index
, 1);
300 m_selectionManager
->beginAnchoredSelection(index
);
304 void KItemListController::slotAutoActivationTimeout()
306 if (!m_model
|| !m_view
) {
310 const int index
= m_autoActivationTimer
->property("index").toInt();
311 if (index
< 0 || index
>= m_model
->count()) {
315 if (m_model
->supportsDropping(index
)) {
316 if (m_view
->supportsItemExpanding() && m_model
->isExpandable(index
)) {
317 const bool expanded
= m_model
->isExpanded(index
);
318 m_model
->setExpanded(index
, !expanded
);
320 emit
itemActivated(index
);
325 bool KItemListController::inputMethodEvent(QInputMethodEvent
* event
)
331 bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent
* event
, const QTransform
& transform
)
337 m_pressedMousePos
= transform
.map(event
->pos());
338 m_pressedIndex
= m_view
->itemAt(m_pressedMousePos
);
340 if (m_view
->isAboveExpansionToggle(m_pressedIndex
, m_pressedMousePos
)) {
341 m_selectionManager
->setCurrentItem(m_pressedIndex
);
345 m_selectionTogglePressed
= m_view
->isAboveSelectionToggle(m_pressedIndex
, m_pressedMousePos
);
346 if (m_selectionTogglePressed
) {
347 m_selectionManager
->setSelected(m_pressedIndex
, 1, KItemListSelectionManager::Toggle
);
351 const bool shiftPressed
= event
->modifiers() & Qt::ShiftModifier
;
352 const bool controlPressed
= event
->modifiers() & Qt::ControlModifier
;
354 if (m_selectionBehavior
== SingleSelection
) {
355 m_selectionManager
->clearSelection();
359 // Finish the anchored selection before the current index is changed
360 m_selectionManager
->endAnchoredSelection();
363 if (m_pressedIndex
>= 0) {
364 m_selectionManager
->setCurrentItem(m_pressedIndex
);
366 switch (m_selectionBehavior
) {
370 case SingleSelection
:
371 m_selectionManager
->setSelected(m_pressedIndex
);
375 if (controlPressed
) {
376 m_selectionManager
->setSelected(m_pressedIndex
, 1, KItemListSelectionManager::Toggle
);
377 m_selectionManager
->beginAnchoredSelection(m_pressedIndex
);
378 } else if (event
->buttons() & Qt::RightButton
) {
379 // Only clear the selection if a context menu is requested above a non-selected item
380 if (!m_selectionManager
->selectedItems().contains(m_pressedIndex
)) {
381 m_selectionManager
->setSelectedItems(QSet
<int>() << m_pressedIndex
);
383 } else if (!shiftPressed
|| !m_selectionManager
->isAnchoredSelectionActive()) {
384 // Select the pressed item and start a new anchored selection
385 m_selectionManager
->setSelected(m_pressedIndex
, 1, KItemListSelectionManager::Select
);
386 m_selectionManager
->beginAnchoredSelection(m_pressedIndex
);
395 if (event
->buttons() & Qt::RightButton
) {
396 emit
itemContextMenuRequested(m_pressedIndex
, event
->screenPos());
402 if (event
->buttons() & Qt::RightButton
) {
403 m_selectionManager
->clearSelection();
405 const QRectF headerBounds
= m_view
->headerBoundaries();
406 if (headerBounds
.contains(event
->pos())) {
407 emit
headerContextMenuRequested(event
->screenPos());
409 emit
viewContextMenuRequested(event
->screenPos());
414 if (m_selectionBehavior
== MultiSelection
) {
415 QPointF startPos
= m_pressedMousePos
;
416 if (m_view
->scrollOrientation() == Qt::Vertical
) {
417 startPos
.ry() += m_view
->scrollOffset();
418 if (m_view
->itemSize().width() < 0) {
419 // Use a special rubberband for views that have only one column and
420 // expand the rubberband to use the whole width of the view.
424 startPos
.rx() += m_view
->scrollOffset();
427 m_oldSelection
= m_selectionManager
->selectedItems();
428 KItemListRubberBand
* rubberBand
= m_view
->rubberBand();
429 rubberBand
->setStartPosition(startPos
);
430 rubberBand
->setEndPosition(startPos
);
431 rubberBand
->setActive(true);
432 connect(rubberBand
, SIGNAL(endPositionChanged(QPointF
,QPointF
)), this, SLOT(slotRubberBandChanged()));
433 m_view
->setAutoScroll(true);
439 bool KItemListController::mouseMoveEvent(QGraphicsSceneMouseEvent
* event
, const QTransform
& transform
)
445 if (m_pressedIndex
>= 0) {
446 // Check whether a dragging should be started
447 if (event
->buttons() & Qt::LeftButton
) {
448 const QPointF pos
= transform
.map(event
->pos());
449 if ((pos
- m_pressedMousePos
).manhattanLength() >= QApplication::startDragDistance()) {
450 if (!m_selectionManager
->isSelected(m_pressedIndex
)) {
451 // Always assure that the dragged item gets selected. Usually this is already
452 // done on the mouse-press event, but when using the selection-toggle on a
453 // selected item the dragged item is not selected yet.
454 m_selectionManager
->setSelected(m_pressedIndex
, 1, KItemListSelectionManager::Toggle
);
460 KItemListRubberBand
* rubberBand
= m_view
->rubberBand();
461 if (rubberBand
->isActive()) {
462 QPointF endPos
= transform
.map(event
->pos());
464 // Update the current item.
465 const int newCurrent
= m_view
->itemAt(endPos
);
466 if (newCurrent
>= 0) {
467 // It's expected that the new current index is also the new anchor (bug 163451).
468 m_selectionManager
->endAnchoredSelection();
469 m_selectionManager
->setCurrentItem(newCurrent
);
470 m_selectionManager
->beginAnchoredSelection(newCurrent
);
473 if (m_view
->scrollOrientation() == Qt::Vertical
) {
474 endPos
.ry() += m_view
->scrollOffset();
475 if (m_view
->itemSize().width() < 0) {
476 // Use a special rubberband for views that have only one column and
477 // expand the rubberband to use the whole width of the view.
478 endPos
.setX(m_view
->size().width());
481 endPos
.rx() += m_view
->scrollOffset();
483 rubberBand
->setEndPosition(endPos
);
490 bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent
* event
, const QTransform
& transform
)
496 const bool isAboveSelectionToggle
= m_view
->isAboveSelectionToggle(m_pressedIndex
, m_pressedMousePos
);
497 if (isAboveSelectionToggle
) {
498 m_selectionTogglePressed
= false;
502 if (!isAboveSelectionToggle
&& m_selectionTogglePressed
) {
503 m_selectionManager
->setSelected(m_pressedIndex
, 1, KItemListSelectionManager::Toggle
);
504 m_selectionTogglePressed
= false;
508 const bool shiftOrControlPressed
= event
->modifiers() & Qt::ShiftModifier
||
509 event
->modifiers() & Qt::ControlModifier
;
511 bool clearSelection
= !shiftOrControlPressed
&& event
->button() != Qt::RightButton
;
513 KItemListRubberBand
* rubberBand
= m_view
->rubberBand();
514 if (rubberBand
->isActive()) {
515 disconnect(rubberBand
, SIGNAL(endPositionChanged(QPointF
,QPointF
)), this, SLOT(slotRubberBandChanged()));
516 rubberBand
->setActive(false);
517 m_oldSelection
.clear();
518 m_view
->setAutoScroll(false);
520 if (rubberBand
->startPosition() != rubberBand
->endPosition()) {
521 clearSelection
= false;
525 const QPointF pos
= transform
.map(event
->pos());
526 const int index
= m_view
->itemAt(pos
);
528 if (index
>= 0 && index
== m_pressedIndex
) {
529 // The release event is done above the same item as the press event
531 if (clearSelection
) {
532 // Clear the previous selection but reselect the current index
533 m_selectionManager
->setSelectedItems(QSet
<int>() << index
);
536 if (event
->button() & Qt::LeftButton
) {
537 bool emitItemActivated
= true;
538 if (m_view
->isAboveExpansionToggle(index
, pos
)) {
539 const bool expanded
= m_model
->isExpanded(index
);
540 m_model
->setExpanded(index
, !expanded
);
542 emit
itemExpansionToggleClicked(index
);
543 emitItemActivated
= false;
544 } else if (shiftOrControlPressed
) {
545 // The mouse click should only update the selection, not trigger the item
546 emitItemActivated
= false;
547 } else if (!KGlobalSettings::singleClick()) {
548 emitItemActivated
= false;
550 if (emitItemActivated
) {
551 emit
itemActivated(index
);
553 } else if (event
->button() & Qt::MidButton
) {
554 emit
itemMiddleClicked(index
);
556 } else if (clearSelection
) {
557 m_selectionManager
->clearSelection();
560 m_pressedMousePos
= QPointF();
565 bool KItemListController::mouseDoubleClickEvent(QGraphicsSceneMouseEvent
* event
, const QTransform
& transform
)
567 const QPointF pos
= transform
.map(event
->pos());
568 const int index
= m_view
->itemAt(pos
);
570 bool emitItemActivated
= !KGlobalSettings::singleClick() &&
571 (event
->button() & Qt::LeftButton
) &&
572 index
>= 0 && index
< m_model
->count();
573 if (emitItemActivated
) {
574 emit
itemActivated(index
);
579 bool KItemListController::dragEnterEvent(QGraphicsSceneDragDropEvent
* event
, const QTransform
& transform
)
586 bool KItemListController::dragLeaveEvent(QGraphicsSceneDragDropEvent
* event
, const QTransform
& transform
)
593 bool KItemListController::dragMoveEvent(QGraphicsSceneDragDropEvent
* event
, const QTransform
& transform
)
596 if (!m_model
|| !m_view
) {
600 KItemListWidget
* oldHoveredWidget
= hoveredWidget();
602 const QPointF pos
= transform
.map(event
->pos());
603 KItemListWidget
* newHoveredWidget
= widgetForPos(pos
);
605 if (oldHoveredWidget
!= newHoveredWidget
) {
606 m_autoActivationTimer
->stop();
608 if (oldHoveredWidget
) {
609 oldHoveredWidget
->setHovered(false);
610 emit
itemUnhovered(oldHoveredWidget
->index());
613 if (newHoveredWidget
) {
614 const int index
= newHoveredWidget
->index();
615 if (m_model
->supportsDropping(index
)) {
616 newHoveredWidget
->setHovered(true);
618 emit
itemHovered(index
);
620 if (m_autoActivationTimer
->interval() >= 0) {
621 m_autoActivationTimer
->setProperty("index", index
);
622 m_autoActivationTimer
->start();
630 bool KItemListController::dropEvent(QGraphicsSceneDragDropEvent
* event
, const QTransform
& transform
)
637 m_autoActivationTimer
->stop();
639 const QPointF pos
= transform
.map(event
->pos());
640 const int index
= m_view
->itemAt(pos
);
641 emit
itemDropEvent(index
, event
);
646 bool KItemListController::hoverEnterEvent(QGraphicsSceneHoverEvent
* event
, const QTransform
& transform
)
653 bool KItemListController::hoverMoveEvent(QGraphicsSceneHoverEvent
* event
, const QTransform
& transform
)
656 if (!m_model
|| !m_view
) {
660 KItemListWidget
* oldHoveredWidget
= hoveredWidget();
661 const QPointF pos
= transform
.map(event
->pos());
662 KItemListWidget
* newHoveredWidget
= widgetForPos(pos
);
664 if (oldHoveredWidget
!= newHoveredWidget
) {
665 if (oldHoveredWidget
) {
666 oldHoveredWidget
->setHovered(false);
667 emit
itemUnhovered(oldHoveredWidget
->index());
670 if (newHoveredWidget
) {
671 newHoveredWidget
->setHovered(true);
672 emit
itemHovered(newHoveredWidget
->index());
679 bool KItemListController::hoverLeaveEvent(QGraphicsSceneHoverEvent
* event
, const QTransform
& transform
)
684 if (!m_model
|| !m_view
) {
688 foreach (KItemListWidget
* widget
, m_view
->visibleItemListWidgets()) {
689 if (widget
->isHovered()) {
690 widget
->setHovered(false);
691 emit
itemUnhovered(widget
->index());
697 bool KItemListController::wheelEvent(QGraphicsSceneWheelEvent
* event
, const QTransform
& transform
)
704 bool KItemListController::resizeEvent(QGraphicsSceneResizeEvent
* event
, const QTransform
& transform
)
711 bool KItemListController::processEvent(QEvent
* event
, const QTransform
& transform
)
717 switch (event
->type()) {
718 case QEvent::KeyPress
:
719 return keyPressEvent(static_cast<QKeyEvent
*>(event
));
720 case QEvent::InputMethod
:
721 return inputMethodEvent(static_cast<QInputMethodEvent
*>(event
));
722 case QEvent::GraphicsSceneMousePress
:
723 return mousePressEvent(static_cast<QGraphicsSceneMouseEvent
*>(event
), QTransform());
724 case QEvent::GraphicsSceneMouseMove
:
725 return mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent
*>(event
), QTransform());
726 case QEvent::GraphicsSceneMouseRelease
:
727 return mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent
*>(event
), QTransform());
728 case QEvent::GraphicsSceneMouseDoubleClick
:
729 return mouseDoubleClickEvent(static_cast<QGraphicsSceneMouseEvent
*>(event
), QTransform());
730 case QEvent::GraphicsSceneWheel
:
731 return wheelEvent(static_cast<QGraphicsSceneWheelEvent
*>(event
), QTransform());
732 case QEvent::GraphicsSceneDragEnter
:
733 return dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent
*>(event
), QTransform());
734 case QEvent::GraphicsSceneDragLeave
:
735 return dragLeaveEvent(static_cast<QGraphicsSceneDragDropEvent
*>(event
), QTransform());
736 case QEvent::GraphicsSceneDragMove
:
737 return dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent
*>(event
), QTransform());
738 case QEvent::GraphicsSceneDrop
:
739 return dropEvent(static_cast<QGraphicsSceneDragDropEvent
*>(event
), QTransform());
740 case QEvent::GraphicsSceneHoverEnter
:
741 return hoverEnterEvent(static_cast<QGraphicsSceneHoverEvent
*>(event
), QTransform());
742 case QEvent::GraphicsSceneHoverMove
:
743 return hoverMoveEvent(static_cast<QGraphicsSceneHoverEvent
*>(event
), QTransform());
744 case QEvent::GraphicsSceneHoverLeave
:
745 return hoverLeaveEvent(static_cast<QGraphicsSceneHoverEvent
*>(event
), QTransform());
746 case QEvent::GraphicsSceneResize
:
747 return resizeEvent(static_cast<QGraphicsSceneResizeEvent
*>(event
), transform
);
755 void KItemListController::slotViewScrollOffsetChanged(qreal current
, qreal previous
)
761 KItemListRubberBand
* rubberBand
= m_view
->rubberBand();
762 if (rubberBand
->isActive()) {
763 const qreal diff
= current
- previous
;
764 // TODO: Ideally just QCursor::pos() should be used as
765 // new end-position but it seems there is no easy way
766 // to have something like QWidget::mapFromGlobal() for QGraphicsWidget
767 // (... or I just missed an easy way to do the mapping)
768 QPointF endPos
= rubberBand
->endPosition();
769 if (m_view
->scrollOrientation() == Qt::Vertical
) {
775 rubberBand
->setEndPosition(endPos
);
779 void KItemListController::slotRubberBandChanged()
781 if (!m_view
|| !m_model
|| m_model
->count() <= 0) {
785 const KItemListRubberBand
* rubberBand
= m_view
->rubberBand();
786 const QPointF startPos
= rubberBand
->startPosition();
787 const QPointF endPos
= rubberBand
->endPosition();
788 QRectF rubberBandRect
= QRectF(startPos
, endPos
).normalized();
790 const bool scrollVertical
= (m_view
->scrollOrientation() == Qt::Vertical
);
791 if (scrollVertical
) {
792 rubberBandRect
.translate(0, -m_view
->scrollOffset());
794 rubberBandRect
.translate(-m_view
->scrollOffset(), 0);
797 if (!m_oldSelection
.isEmpty()) {
798 // Clear the old selection that was available before the rubberband has
799 // been activated in case if no Shift- or Control-key are pressed
800 const bool shiftOrControlPressed
= QApplication::keyboardModifiers() & Qt::ShiftModifier
||
801 QApplication::keyboardModifiers() & Qt::ControlModifier
;
802 if (!shiftOrControlPressed
) {
803 m_oldSelection
.clear();
807 QSet
<int> selectedItems
;
809 // Select all visible items that intersect with the rubberband
810 foreach (const KItemListWidget
* widget
, m_view
->visibleItemListWidgets()) {
811 const int index
= widget
->index();
813 const QRectF widgetRect
= m_view
->itemRect(index
);
814 if (widgetRect
.intersects(rubberBandRect
)) {
815 const QRectF iconRect
= widget
->iconRect().translated(widgetRect
.topLeft());
816 const QRectF textRect
= widget
->textRect().translated(widgetRect
.topLeft());
817 if (iconRect
.intersects(rubberBandRect
) || textRect
.intersects(rubberBandRect
)) {
818 selectedItems
.insert(index
);
823 // Select all invisible items that intersect with the rubberband. Instead of
824 // iterating all items only the area which might be touched by the rubberband
826 const bool increaseIndex
= scrollVertical
?
827 startPos
.y() > endPos
.y(): startPos
.x() > endPos
.x();
829 int index
= increaseIndex
? m_view
->lastVisibleIndex() + 1 : m_view
->firstVisibleIndex() - 1;
830 bool selectionFinished
= false;
832 const QRectF widgetRect
= m_view
->itemRect(index
);
833 if (widgetRect
.intersects(rubberBandRect
)) {
834 selectedItems
.insert(index
);
839 selectionFinished
= (index
>= m_model
->count()) ||
840 ( scrollVertical
&& widgetRect
.top() > rubberBandRect
.bottom()) ||
841 (!scrollVertical
&& widgetRect
.left() > rubberBandRect
.right());
844 selectionFinished
= (index
< 0) ||
845 ( scrollVertical
&& widgetRect
.bottom() < rubberBandRect
.top()) ||
846 (!scrollVertical
&& widgetRect
.right() < rubberBandRect
.left());
848 } while (!selectionFinished
);
850 if (QApplication::keyboardModifiers() & Qt::ControlModifier
) {
851 // If Control is pressed, the selection state of all items in the rubberband is toggled.
852 // Therefore, the new selection contains:
853 // 1. All previously selected items which are not inside the rubberband, and
854 // 2. all items inside the rubberband which have not been selected previously.
855 m_selectionManager
->setSelectedItems((m_oldSelection
- selectedItems
) + (selectedItems
- m_oldSelection
));
858 m_selectionManager
->setSelectedItems(selectedItems
+ m_oldSelection
);
862 void KItemListController::startDragging()
864 if (!m_view
|| !m_model
) {
868 const QSet
<int> selectedItems
= m_selectionManager
->selectedItems();
869 if (selectedItems
.isEmpty()) {
873 QMimeData
* data
= m_model
->createMimeData(selectedItems
);
878 // The created drag object will be owned and deleted
879 // by QApplication::activeWindow().
880 QDrag
* drag
= new QDrag(QApplication::activeWindow());
881 drag
->setMimeData(data
);
883 const QPixmap pixmap
= m_view
->createDragPixmap(selectedItems
);
884 drag
->setPixmap(pixmap
);
886 drag
->exec(Qt::MoveAction
| Qt::CopyAction
| Qt::LinkAction
, Qt::IgnoreAction
);
889 KItemListWidget
* KItemListController::hoveredWidget() const
893 foreach (KItemListWidget
* widget
, m_view
->visibleItemListWidgets()) {
894 if (widget
->isHovered()) {
902 KItemListWidget
* KItemListController::widgetForPos(const QPointF
& pos
) const
906 foreach (KItemListWidget
* widget
, m_view
->visibleItemListWidgets()) {
907 const QPointF mappedPos
= widget
->mapFromItem(m_view
, pos
);
909 const bool hovered
= widget
->contains(mappedPos
) &&
910 !widget
->expansionToggleRect().contains(mappedPos
);
919 #include "kitemlistcontroller.moc"