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());
463 if (m_view
->scrollOrientation() == Qt::Vertical
) {
464 endPos
.ry() += m_view
->scrollOffset();
465 if (m_view
->itemSize().width() < 0) {
466 // Use a special rubberband for views that have only one column and
467 // expand the rubberband to use the whole width of the view.
468 endPos
.setX(m_view
->size().width());
471 endPos
.rx() += m_view
->scrollOffset();
473 rubberBand
->setEndPosition(endPos
);
480 bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent
* event
, const QTransform
& transform
)
486 const bool isAboveSelectionToggle
= m_view
->isAboveSelectionToggle(m_pressedIndex
, m_pressedMousePos
);
487 if (isAboveSelectionToggle
) {
488 m_selectionTogglePressed
= false;
492 if (!isAboveSelectionToggle
&& m_selectionTogglePressed
) {
493 m_selectionManager
->setSelected(m_pressedIndex
, 1, KItemListSelectionManager::Toggle
);
494 m_selectionTogglePressed
= false;
498 const bool shiftOrControlPressed
= event
->modifiers() & Qt::ShiftModifier
||
499 event
->modifiers() & Qt::ControlModifier
;
501 bool clearSelection
= !shiftOrControlPressed
&& event
->button() != Qt::RightButton
;
503 KItemListRubberBand
* rubberBand
= m_view
->rubberBand();
504 if (rubberBand
->isActive()) {
505 disconnect(rubberBand
, SIGNAL(endPositionChanged(QPointF
,QPointF
)), this, SLOT(slotRubberBandChanged()));
506 rubberBand
->setActive(false);
507 m_oldSelection
.clear();
508 m_view
->setAutoScroll(false);
510 if (rubberBand
->startPosition() != rubberBand
->endPosition()) {
511 clearSelection
= false;
515 const QPointF pos
= transform
.map(event
->pos());
516 const int index
= m_view
->itemAt(pos
);
518 if (index
>= 0 && index
== m_pressedIndex
) {
519 // The release event is done above the same item as the press event
521 if (clearSelection
) {
522 // Clear the previous selection but reselect the current index
523 m_selectionManager
->setSelectedItems(QSet
<int>() << index
);
526 if (event
->button() & Qt::LeftButton
) {
527 bool emitItemActivated
= true;
528 if (m_view
->isAboveExpansionToggle(index
, pos
)) {
529 const bool expanded
= m_model
->isExpanded(index
);
530 m_model
->setExpanded(index
, !expanded
);
532 emit
itemExpansionToggleClicked(index
);
533 emitItemActivated
= false;
534 } else if (shiftOrControlPressed
) {
535 // The mouse click should only update the selection, not trigger the item
536 emitItemActivated
= false;
537 } else if (!KGlobalSettings::singleClick()) {
538 emitItemActivated
= false;
540 if (emitItemActivated
) {
541 emit
itemActivated(index
);
543 } else if (event
->button() & Qt::MidButton
) {
544 emit
itemMiddleClicked(index
);
546 } else if (clearSelection
) {
547 m_selectionManager
->clearSelection();
550 m_pressedMousePos
= QPointF();
555 bool KItemListController::mouseDoubleClickEvent(QGraphicsSceneMouseEvent
* event
, const QTransform
& transform
)
557 const QPointF pos
= transform
.map(event
->pos());
558 const int index
= m_view
->itemAt(pos
);
560 bool emitItemActivated
= !KGlobalSettings::singleClick() &&
561 (event
->button() & Qt::LeftButton
) &&
562 index
>= 0 && index
< m_model
->count();
563 if (emitItemActivated
) {
564 emit
itemActivated(index
);
569 bool KItemListController::dragEnterEvent(QGraphicsSceneDragDropEvent
* event
, const QTransform
& transform
)
576 bool KItemListController::dragLeaveEvent(QGraphicsSceneDragDropEvent
* event
, const QTransform
& transform
)
583 bool KItemListController::dragMoveEvent(QGraphicsSceneDragDropEvent
* event
, const QTransform
& transform
)
586 if (!m_model
|| !m_view
) {
590 KItemListWidget
* oldHoveredWidget
= hoveredWidget();
592 const QPointF pos
= transform
.map(event
->pos());
593 KItemListWidget
* newHoveredWidget
= widgetForPos(pos
);
595 if (oldHoveredWidget
!= newHoveredWidget
) {
596 m_autoActivationTimer
->stop();
598 if (oldHoveredWidget
) {
599 oldHoveredWidget
->setHovered(false);
600 emit
itemUnhovered(oldHoveredWidget
->index());
603 if (newHoveredWidget
) {
604 const int index
= newHoveredWidget
->index();
605 if (m_model
->supportsDropping(index
)) {
606 newHoveredWidget
->setHovered(true);
608 emit
itemHovered(index
);
610 if (m_autoActivationTimer
->interval() >= 0) {
611 m_autoActivationTimer
->setProperty("index", index
);
612 m_autoActivationTimer
->start();
620 bool KItemListController::dropEvent(QGraphicsSceneDragDropEvent
* event
, const QTransform
& transform
)
627 m_autoActivationTimer
->stop();
629 const QPointF pos
= transform
.map(event
->pos());
630 const int index
= m_view
->itemAt(pos
);
631 emit
itemDropEvent(index
, event
);
636 bool KItemListController::hoverEnterEvent(QGraphicsSceneHoverEvent
* event
, const QTransform
& transform
)
643 bool KItemListController::hoverMoveEvent(QGraphicsSceneHoverEvent
* event
, const QTransform
& transform
)
646 if (!m_model
|| !m_view
) {
650 KItemListWidget
* oldHoveredWidget
= hoveredWidget();
651 const QPointF pos
= transform
.map(event
->pos());
652 KItemListWidget
* newHoveredWidget
= widgetForPos(pos
);
654 if (oldHoveredWidget
!= newHoveredWidget
) {
655 if (oldHoveredWidget
) {
656 oldHoveredWidget
->setHovered(false);
657 emit
itemUnhovered(oldHoveredWidget
->index());
660 if (newHoveredWidget
) {
661 newHoveredWidget
->setHovered(true);
662 emit
itemHovered(newHoveredWidget
->index());
669 bool KItemListController::hoverLeaveEvent(QGraphicsSceneHoverEvent
* event
, const QTransform
& transform
)
674 if (!m_model
|| !m_view
) {
678 foreach (KItemListWidget
* widget
, m_view
->visibleItemListWidgets()) {
679 if (widget
->isHovered()) {
680 widget
->setHovered(false);
681 emit
itemUnhovered(widget
->index());
687 bool KItemListController::wheelEvent(QGraphicsSceneWheelEvent
* event
, const QTransform
& transform
)
694 bool KItemListController::resizeEvent(QGraphicsSceneResizeEvent
* event
, const QTransform
& transform
)
701 bool KItemListController::processEvent(QEvent
* event
, const QTransform
& transform
)
707 switch (event
->type()) {
708 case QEvent::KeyPress
:
709 return keyPressEvent(static_cast<QKeyEvent
*>(event
));
710 case QEvent::InputMethod
:
711 return inputMethodEvent(static_cast<QInputMethodEvent
*>(event
));
712 case QEvent::GraphicsSceneMousePress
:
713 return mousePressEvent(static_cast<QGraphicsSceneMouseEvent
*>(event
), QTransform());
714 case QEvent::GraphicsSceneMouseMove
:
715 return mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent
*>(event
), QTransform());
716 case QEvent::GraphicsSceneMouseRelease
:
717 return mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent
*>(event
), QTransform());
718 case QEvent::GraphicsSceneMouseDoubleClick
:
719 return mouseDoubleClickEvent(static_cast<QGraphicsSceneMouseEvent
*>(event
), QTransform());
720 case QEvent::GraphicsSceneWheel
:
721 return wheelEvent(static_cast<QGraphicsSceneWheelEvent
*>(event
), QTransform());
722 case QEvent::GraphicsSceneDragEnter
:
723 return dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent
*>(event
), QTransform());
724 case QEvent::GraphicsSceneDragLeave
:
725 return dragLeaveEvent(static_cast<QGraphicsSceneDragDropEvent
*>(event
), QTransform());
726 case QEvent::GraphicsSceneDragMove
:
727 return dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent
*>(event
), QTransform());
728 case QEvent::GraphicsSceneDrop
:
729 return dropEvent(static_cast<QGraphicsSceneDragDropEvent
*>(event
), QTransform());
730 case QEvent::GraphicsSceneHoverEnter
:
731 return hoverEnterEvent(static_cast<QGraphicsSceneHoverEvent
*>(event
), QTransform());
732 case QEvent::GraphicsSceneHoverMove
:
733 return hoverMoveEvent(static_cast<QGraphicsSceneHoverEvent
*>(event
), QTransform());
734 case QEvent::GraphicsSceneHoverLeave
:
735 return hoverLeaveEvent(static_cast<QGraphicsSceneHoverEvent
*>(event
), QTransform());
736 case QEvent::GraphicsSceneResize
:
737 return resizeEvent(static_cast<QGraphicsSceneResizeEvent
*>(event
), transform
);
745 void KItemListController::slotViewScrollOffsetChanged(qreal current
, qreal previous
)
751 KItemListRubberBand
* rubberBand
= m_view
->rubberBand();
752 if (rubberBand
->isActive()) {
753 const qreal diff
= current
- previous
;
754 // TODO: Ideally just QCursor::pos() should be used as
755 // new end-position but it seems there is no easy way
756 // to have something like QWidget::mapFromGlobal() for QGraphicsWidget
757 // (... or I just missed an easy way to do the mapping)
758 QPointF endPos
= rubberBand
->endPosition();
759 if (m_view
->scrollOrientation() == Qt::Vertical
) {
765 rubberBand
->setEndPosition(endPos
);
769 void KItemListController::slotRubberBandChanged()
771 if (!m_view
|| !m_model
|| m_model
->count() <= 0) {
775 const KItemListRubberBand
* rubberBand
= m_view
->rubberBand();
776 const QPointF startPos
= rubberBand
->startPosition();
777 const QPointF endPos
= rubberBand
->endPosition();
778 QRectF rubberBandRect
= QRectF(startPos
, endPos
).normalized();
780 const bool scrollVertical
= (m_view
->scrollOrientation() == Qt::Vertical
);
781 if (scrollVertical
) {
782 rubberBandRect
.translate(0, -m_view
->scrollOffset());
784 rubberBandRect
.translate(-m_view
->scrollOffset(), 0);
787 if (!m_oldSelection
.isEmpty()) {
788 // Clear the old selection that was available before the rubberband has
789 // been activated in case if no Shift- or Control-key are pressed
790 const bool shiftOrControlPressed
= QApplication::keyboardModifiers() & Qt::ShiftModifier
||
791 QApplication::keyboardModifiers() & Qt::ControlModifier
;
792 if (!shiftOrControlPressed
) {
793 m_oldSelection
.clear();
797 QSet
<int> selectedItems
;
799 // Select all visible items that intersect with the rubberband
800 foreach (const KItemListWidget
* widget
, m_view
->visibleItemListWidgets()) {
801 const int index
= widget
->index();
803 const QRectF widgetRect
= m_view
->itemRect(index
);
804 if (widgetRect
.intersects(rubberBandRect
)) {
805 const QRectF iconRect
= widget
->iconRect().translated(widgetRect
.topLeft());
806 const QRectF textRect
= widget
->textRect().translated(widgetRect
.topLeft());
807 if (iconRect
.intersects(rubberBandRect
) || textRect
.intersects(rubberBandRect
)) {
808 selectedItems
.insert(index
);
813 // Select all invisible items that intersect with the rubberband. Instead of
814 // iterating all items only the area which might be touched by the rubberband
816 const bool increaseIndex
= scrollVertical
?
817 startPos
.y() > endPos
.y(): startPos
.x() > endPos
.x();
819 int index
= increaseIndex
? m_view
->lastVisibleIndex() + 1 : m_view
->firstVisibleIndex() - 1;
820 bool selectionFinished
= false;
822 const QRectF widgetRect
= m_view
->itemRect(index
);
823 if (widgetRect
.intersects(rubberBandRect
)) {
824 selectedItems
.insert(index
);
829 selectionFinished
= (index
>= m_model
->count()) ||
830 ( scrollVertical
&& widgetRect
.top() > rubberBandRect
.bottom()) ||
831 (!scrollVertical
&& widgetRect
.left() > rubberBandRect
.right());
834 selectionFinished
= (index
< 0) ||
835 ( scrollVertical
&& widgetRect
.bottom() < rubberBandRect
.top()) ||
836 (!scrollVertical
&& widgetRect
.right() < rubberBandRect
.left());
838 } while (!selectionFinished
);
840 if (QApplication::keyboardModifiers() & Qt::ControlModifier
) {
841 // If Control is pressed, the selection state of all items in the rubberband is toggled.
842 // Therefore, the new selection contains:
843 // 1. All previously selected items which are not inside the rubberband, and
844 // 2. all items inside the rubberband which have not been selected previously.
845 m_selectionManager
->setSelectedItems((m_oldSelection
- selectedItems
) + (selectedItems
- m_oldSelection
));
848 m_selectionManager
->setSelectedItems(selectedItems
+ m_oldSelection
);
852 void KItemListController::startDragging()
854 if (!m_view
|| !m_model
) {
858 const QSet
<int> selectedItems
= m_selectionManager
->selectedItems();
859 if (selectedItems
.isEmpty()) {
863 QMimeData
* data
= m_model
->createMimeData(selectedItems
);
868 // The created drag object will be owned and deleted
869 // by QApplication::activeWindow().
870 QDrag
* drag
= new QDrag(QApplication::activeWindow());
871 drag
->setMimeData(data
);
873 const QPixmap pixmap
= m_view
->createDragPixmap(selectedItems
);
874 drag
->setPixmap(pixmap
);
876 drag
->exec(Qt::MoveAction
| Qt::CopyAction
| Qt::LinkAction
, Qt::IgnoreAction
);
879 KItemListWidget
* KItemListController::hoveredWidget() const
883 foreach (KItemListWidget
* widget
, m_view
->visibleItemListWidgets()) {
884 if (widget
->isHovered()) {
892 KItemListWidget
* KItemListController::widgetForPos(const QPointF
& pos
) const
896 foreach (KItemListWidget
* widget
, m_view
->visibleItemListWidgets()) {
897 const QPointF mappedPos
= widget
->mapFromItem(m_view
, pos
);
899 const bool hovered
= widget
->contains(mappedPos
) &&
900 !widget
->expansionToggleRect().contains(mappedPos
);
909 #include "kitemlistcontroller.moc"