#include "kitemlistselectionmanager.h"
#include <QApplication>
+#include <QDrag>
#include <QEvent>
#include <QGraphicsSceneEvent>
+#include <QMimeData>
#include <KDebug>
KItemListController::KItemListController(QObject* parent) :
QObject(parent),
+ m_dragging(false),
m_selectionBehavior(NoSelection),
m_model(0),
m_view(0),
m_selectionManager(new KItemListSelectionManager(this)),
- m_pressedIndex(-1)
+ m_pressedIndex(-1),
+ m_pressedMousePos(),
+ m_oldSelection()
{
}
return false;
}
- const QPointF pos = transform.map(event->pos());
- m_pressedIndex = m_view->itemAt(pos);
+ m_dragging = false;
+ 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)) {
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();
}
return true;
} else {
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) {
} else {
startPos.rx() += m_view->offset();
}
+
+ m_oldSelection = m_selectionManager->selectedItems();
rubberBand->setStartPosition(startPos);
rubberBand->setEndPosition(startPos);
rubberBand->setActive(true);
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 (!m_dragging && (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()) {
+ m_dragging = true;
}
- } 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;
return false;
}
+ const bool shiftOrControlPressed = event->modifiers() & Qt::ShiftModifier ||
+ event->modifiers() & Qt::ControlModifier;
+
+ bool clearSelection = !shiftOrControlPressed && !m_dragging && !(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();
+
+ 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
+
+ if (clearSelection) {
+ // Clear the previous selection but reselect the current index
+ m_selectionManager->setSelectedItems(QSet<int>() << index);
+ }
+
bool emitItemClicked = true;
if (event->button() & Qt::LeftButton) {
if (m_view->isAboveExpansionToggle(index, pos)) {
emit itemExpansionToggleClicked(index);
emitItemClicked = false;
- }
- else if (shiftOrControlPressed) {
+ } else if (shiftOrControlPressed) {
// The mouse click should only update the selection, not trigger the item
emitItemClicked = false;
}
if (emitItemClicked) {
emit itemClicked(index, event->button());
}
- } else if (!shiftOrControlPressed) {
+ } else if (clearSelection) {
m_selectionManager->clearSelection();
}
+ m_dragging = false;
+ m_pressedMousePos = QPointF();
m_pressedIndex = -1;
return false;
}
{
Q_UNUSED(event);
Q_UNUSED(transform);
+
+ m_dragging = false;
return false;
}
rubberBandRect.translate(-m_view->offset(), 0);
}
- QSet<int> 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();
}
}
}
} while (!selectionFinished);
- m_selectionManager->setSelectedItems(selectedItems + previousSelectedItems);
+ m_selectionManager->setSelectedItems(selectedItems + m_oldSelection);
+}
+
+bool KItemListController::startDragging()
+{
+ if (!m_view || !m_model) {
+ return false;
+ }
+
+ const QSet<int> selectedItems = m_selectionManager->selectedItems();
+ QMimeData* data = m_model->createMimeData(selectedItems);
+ if (!data) {
+ return false;
+ }
+
+ // 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);
+ return true;
}
#include "kitemlistcontroller.moc"