From a95883e90fadeddd2f49da6765fb2d79f7ce77bd Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 23 Oct 2009 09:14:39 +0200 Subject: Added visual DnD indicator for left to right flow in QListView Extended the behaviour already present in QAbstractItemView into QListView. This means some code duplication which should maybe be refactored at some point. (Seems to be the price to pay when some delegate does almost the same thing as the base class). No auto-test, as it's a drag-and-drop related task. Reviewed-by: Thierry Task-number: QTBUG-3730 --- src/gui/itemviews/qabstractitemview.h | 1 + src/gui/itemviews/qabstractitemview_p.h | 3 +- src/gui/itemviews/qlistview.cpp | 109 +++++++++++++++++++++++++++++++- src/gui/itemviews/qlistview_p.h | 9 +++ 4 files changed, 119 insertions(+), 3 deletions(-) diff --git a/src/gui/itemviews/qabstractitemview.h b/src/gui/itemviews/qabstractitemview.h index b4f0957..f438148 100644 --- a/src/gui/itemviews/qabstractitemview.h +++ b/src/gui/itemviews/qabstractitemview.h @@ -361,6 +361,7 @@ private: friend class QTreeViewPrivate; // needed to compile with MSVC friend class QAccessibleItemRow; + friend class QListModeViewBase; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstractItemView::EditTriggers) diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h index fcf381a..66b7662 100644 --- a/src/gui/itemviews/qabstractitemview_p.h +++ b/src/gui/itemviews/qabstractitemview_p.h @@ -164,7 +164,8 @@ public: } #ifndef QT_NO_DRAGANDDROP - QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const; + virtual QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const; + inline bool canDecode(QDropEvent *e) const { QStringList modelTypes = model->mimeTypes(); const QMimeData *mime = e->mimeData(); diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index f58f458..109d760 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -853,8 +853,13 @@ void QListView::resizeEvent(QResizeEvent *e) */ void QListView::dragMoveEvent(QDragMoveEvent *e) { - if (!d_func()->commonListView->filterDragMoveEvent(e)) - QAbstractItemView::dragMoveEvent(e); + Q_D(QListView); + if (!d->commonListView->filterDragMoveEvent(e)) { + if (viewMode() == QListView::ListMode && flow() == QListView::LeftToRight) + static_cast(d->commonListView)->dragMoveEvent(e); + else + QAbstractItemView::dragMoveEvent(e); + } } @@ -1804,6 +1809,16 @@ QItemSelection QListViewPrivate::selection(const QRect &rect) const return selection; } +#ifndef QT_NO_DRAGANDDROP +QAbstractItemView::DropIndicatorPosition QListViewPrivate::position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const +{ + if (viewMode == QListView::ListMode && flow == QListView::LeftToRight) + return static_cast(commonListView)->position(pos, rect, idx); + else + return QAbstractItemViewPrivate::position(pos, rect, idx); +} +#endif + /* * Common ListView Implementation */ @@ -1893,6 +1908,96 @@ void QListModeViewBase::paintDragDrop(QPainter *painter) // in IconMode, it makes no sense to show it dd->paintDropIndicator(painter); } + +QAbstractItemView::DropIndicatorPosition QListModeViewBase::position(const QPoint &pos, const QRect &rect, const QModelIndex &index) const +{ + QAbstractItemView::DropIndicatorPosition r = QAbstractItemView::OnViewport; + if (!dd->overwrite) { + const int margin = 2; + if (pos.x() - rect.left() < margin) { + r = QAbstractItemView::AboveItem; // Visually, on the left + } else if (rect.right() - pos.x() < margin) { + r = QAbstractItemView::BelowItem; // Visually, on the right + } else if (rect.contains(pos, true)) { + r = QAbstractItemView::OnItem; + } + } else { + QRect touchingRect = rect; + touchingRect.adjust(-1, -1, 1, 1); + if (touchingRect.contains(pos, false)) { + r = QAbstractItemView::OnItem; + } + } + + if (r == QAbstractItemView::OnItem && (!(dd->model->flags(index) & Qt::ItemIsDropEnabled))) + r = pos.x() < rect.center().x() ? QAbstractItemView::AboveItem : QAbstractItemView::BelowItem; + + return r; +} + +void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event) +{ + if (qq->dragDropMode() == QAbstractItemView::InternalMove + && (event->source() != qq || !(event->possibleActions() & Qt::MoveAction))) + return; + + // ignore by default + event->ignore(); + + QModelIndex index = qq->indexAt(event->pos()); + dd->hover = index; + if (!dd->droppingOnItself(event, index) + && dd->canDecode(event)) { + + if (index.isValid() && dd->showDropIndicator) { + QRect rect = qq->visualRect(index); + dd->dropIndicatorPosition = position(event->pos(), rect, index); + switch (dd->dropIndicatorPosition) { + case QAbstractItemView::AboveItem: + if (dd->isIndexDropEnabled(index.parent())) { + dd->dropIndicatorRect = QRect(rect.left(), rect.top(), 0, rect.height()); + event->accept(); + } else { + dd->dropIndicatorRect = QRect(); + } + break; + case QAbstractItemView::BelowItem: + if (dd->isIndexDropEnabled(index.parent())) { + dd->dropIndicatorRect = QRect(rect.right(), rect.top(), 0, rect.height()); + event->accept(); + } else { + dd->dropIndicatorRect = QRect(); + } + break; + case QAbstractItemView::OnItem: + if (dd->isIndexDropEnabled(index)) { + dd->dropIndicatorRect = rect; + event->accept(); + } else { + dd->dropIndicatorRect = QRect(); + } + break; + case QAbstractItemView::OnViewport: + dd->dropIndicatorRect = QRect(); + if (dd->isIndexDropEnabled(qq->rootIndex())) { + event->accept(); // allow dropping in empty areas + } + break; + } + } else { + dd->dropIndicatorRect = QRect(); + dd->dropIndicatorPosition = QAbstractItemView::OnViewport; + if (dd->isIndexDropEnabled(qq->rootIndex())) { + event->accept(); // allow dropping in empty areas + } + } + dd->viewport->update(); + } // can decode + + if (dd->shouldAutoScroll(event->pos())) + qq->startAutoScroll(); +} + #endif //QT_NO_DRAGANDDROP void QListModeViewBase::updateVerticalScrollBar(const QSize &step) diff --git a/src/gui/itemviews/qlistview_p.h b/src/gui/itemviews/qlistview_p.h index de4c7f3..3f8f9db 100644 --- a/src/gui/itemviews/qlistview_p.h +++ b/src/gui/itemviews/qlistview_p.h @@ -231,6 +231,11 @@ public: #ifndef QT_NO_DRAGANDDROP void paintDragDrop(QPainter *painter); + + // The next two methods are to be used on LefToRight flow only. + // WARNING: Plenty of duplicated code from QAbstractItemView{,Private}. + QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const; + void dragMoveEvent(QDragMoveEvent *e); #endif private: @@ -356,6 +361,10 @@ public: QItemSelection selection(const QRect &rect) const; void selectAll(QItemSelectionModel::SelectionFlags command); +#ifndef QT_NO_DRAGANDDROP + virtual QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const; +#endif + inline void setGridSize(const QSize &size) { grid = size; } inline QSize gridSize() const { return grid; } inline void setWrapping(bool b) { wrap = b; } -- cgit v0.12