From: Peter Penz Date: Tue, 23 Aug 2011 18:55:41 +0000 (+0200) Subject: Rough draft for getting back drag and drop support X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/commitdiff_plain/5ba4aeba3e82f843fb4c5b54daaaf9ae5d8cedac?ds=inline Rough draft for getting back drag and drop support Includes a lot of TODOs but is a base for getting back full drag and drop support quite soon. --- diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp index beb5b5c0a..15aab28d5 100644 --- a/src/kitemviews/kitemlistcontroller.cpp +++ b/src/kitemviews/kitemlistcontroller.cpp @@ -26,19 +26,28 @@ #include "kitemlistrubberband_p.h" #include "kitemlistselectionmanager.h" +// TODO: Remove after moving mimeData() and createDropPixmap() into +// KFileItemModel/KFileItemListView +#include "kfileitemmodel.h" +#include + #include +#include #include #include +#include #include 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_pressedMousePos(), m_oldSelection() { } @@ -234,10 +243,10 @@ bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const return false; } - const QPointF pos = transform.map(event->pos()); - m_pressedIndex = m_view->itemAt(pos); + 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; } @@ -284,7 +293,7 @@ bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const 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) { @@ -312,20 +321,33 @@ bool KItemListController::mouseMoveEvent(QGraphicsSceneMouseEvent* event, const 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) { + const QPointF pos = transform.map(event->pos()); + const qreal minDragDiff = 4; + m_dragging = qAbs(pos.x() - m_pressedMousePos.x()) >= minDragDiff || + qAbs(pos.y() - m_pressedMousePos.y()) >= minDragDiff; + if (m_dragging) { + startDragging(); } - } 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; @@ -342,35 +364,35 @@ bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, con disconnect(rubberBand, SIGNAL(endPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandChanged())); rubberBand->setActive(false); m_oldSelection.clear(); - m_pressedIndex = -1; - return 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 - bool emitItemClicked = true; - if (event->button() & Qt::LeftButton) { - if (m_view->isAboveExpansionToggle(index, pos)) { - emit itemExpansionToggleClicked(index); - emitItemClicked = false; - } - else if (shiftOrControlPressed) { - // The mouse click should only update the selection, not trigger the item - emitItemClicked = false; + } else { + 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 + bool emitItemClicked = true; + if (event->button() & Qt::LeftButton) { + if (m_view->isAboveExpansionToggle(index, pos)) { + emit itemExpansionToggleClicked(index); + emitItemClicked = false; + } else if (shiftOrControlPressed) { + // The mouse click should only update the selection, not trigger the item + emitItemClicked = false; + } } - } - if (emitItemClicked) { - emit itemClicked(index, event->button()); + if (emitItemClicked) { + emit itemClicked(index, event->button()); + } + } else if (!shiftOrControlPressed) { + m_selectionManager->clearSelection(); } - } else if (!shiftOrControlPressed) { - m_selectionManager->clearSelection(); } + m_dragging = false; + m_pressedMousePos = QPointF(); m_pressedIndex = -1; return false; } @@ -407,6 +429,8 @@ bool KItemListController::dropEvent(QGraphicsSceneDragDropEvent* event, const QT { Q_UNUSED(event); Q_UNUSED(transform); + + m_dragging = false; return false; } @@ -637,4 +661,71 @@ void KItemListController::slotRubberBandChanged() m_selectionManager->setSelectedItems(selectedItems + m_oldSelection); } +QPixmap KItemListController::createDragPixmap(const QSet& indexes) const +{ + if (!m_model || !m_view) { + return QPixmap(); + } + + // TODO: The current hack assumes a property "iconPixmap" in the model. The method + // will get an interface of KFileItemList later. + QSetIterator it(indexes); + while (it.hasNext()) { + const int index = it.next(); + // TODO: Only one item is considered currently + QPixmap pixmap = m_model->data(index).value("iconPixmap").value(); + if (pixmap.isNull()) { + KIcon icon(m_model->data(index).value("iconName").toString()); + const QSizeF size = m_view->itemSize(); + pixmap = icon.pixmap(size.toSize()); + } + return pixmap; + } + + return QPixmap(); +} + +QMimeData* KItemListController::createMimeData(const QSet& indexes) const +{ + if (!m_model) { + return 0; + } + + QMimeData* data = new QMimeData(); + + // TODO: Check KDirModel::mimeData() for a good reference implementation + KUrl::List urls; + QSetIterator it(indexes); + while (it.hasNext()) { + const int index = it.next(); + // TODO: Big hack to use KFileItemModel here. Remove after moving mimeData() + // into KFileItemModel. + KFileItemModel* model = qobject_cast(m_model); + Q_ASSERT(model); + const KUrl url = model->fileItem(index).url(); + urls.append(url); + } + + urls.populateMimeData(data); + + return data; +} + +void KItemListController::startDragging() +{ + // The created drag object will be owned and deleted + // by QApplication::activeWindow(). + QDrag* drag = new QDrag(QApplication::activeWindow()); + + const QSet selectedItems = m_selectionManager->selectedItems(); + + const QPixmap pixmap = createDragPixmap(selectedItems); + drag->setPixmap(pixmap); + + QMimeData* data = createMimeData(selectedItems); + drag->setMimeData(data); + + drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction, Qt::IgnoreAction); +} + #include "kitemlistcontroller.moc" diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h index 90850bae1..b56087ce1 100644 --- a/src/kitemviews/kitemlistcontroller.h +++ b/src/kitemviews/kitemlistcontroller.h @@ -26,6 +26,8 @@ #include #include +#include +#include #include class KItemModelBase; @@ -39,6 +41,7 @@ class QGraphicsSceneWheelEvent; class QHideEvent; class QInputMethodEvent; class QKeyEvent; +class QMimeData; class QShowEvent; class QTransform; @@ -130,11 +133,32 @@ private slots: void slotRubberBandChanged(); private: + /** + * @return Pixmap that is used for a drag operation based on the + * items given by \a indexes. + * TODO: Will be moved to KItemListView later + */ + QPixmap createDragPixmap(const QSet& indexes) const; + + /** + * @return MIME-data for the items given by \a indexes. + * TODO: Will be moved to KItemListView or KItemModelBase/KFileItemModel later. + */ + QMimeData* createMimeData(const QSet& indexes) const; + + /** + * Creates a QDrag object to start a drag-operation. + */ + void startDragging(); + +private: + bool m_dragging; SelectionBehavior m_selectionBehavior; KItemModelBase* m_model; KItemListView* m_view; KItemListSelectionManager* m_selectionManager; int m_pressedIndex; + QPointF m_pressedMousePos; /** * When starting a rubberband selection during a Shift- or Control-key has been diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp index 9189cbda3..4bf7159d6 100644 --- a/src/kitemviews/kitemlistview.cpp +++ b/src/kitemviews/kitemlistview.cpp @@ -66,6 +66,7 @@ KItemListView::KItemListView(QGraphicsWidget* parent) : m_mousePos() { setAcceptHoverEvents(true); + setAcceptDrops(true); m_sizeHintResolver = new KItemListSizeHintResolver(this); @@ -459,6 +460,11 @@ void KItemListView::mouseMoveEvent(QGraphicsSceneMouseEvent* event) QGraphicsWidget::mouseMoveEvent(event); } +void KItemListView::dragEnterEvent(QGraphicsSceneDragDropEvent* event) +{ + event->setAccepted(true); +} + QList KItemListView::visibleItemListWidgets() const { return m_visibleItems.values(); diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h index 3f877d236..2a07dbb23 100644 --- a/src/kitemviews/kitemlistview.h +++ b/src/kitemviews/kitemlistview.h @@ -183,6 +183,7 @@ protected: virtual bool event(QEvent* event); virtual void mousePressEvent(QGraphicsSceneMouseEvent* event); virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* event); + virtual void dragEnterEvent(QGraphicsSceneDragDropEvent* event); QList visibleItemListWidgets() const;