From e46003aca365ca66ce7c7cccd47fb52d1da2fb91 Mon Sep 17 00:00:00 2001 From: Peter Penz Date: Tue, 20 Nov 2007 21:11:48 +0000 Subject: [PATCH] Drag & drop fixes for all views: assure that a consistent pixmap for the drag object is used throughout all views (still open yet: KCategorizedView uses its custom code yet) svn path=/trunk/KDE/kdebase/apps/; revision=739322 --- src/CMakeLists.txt | 2 + src/dolphincolumnwidget.cpp | 9 +++- src/dolphincolumnwidget.h | 1 + src/dolphincontroller.cpp | 29 ------------- src/dolphincontroller.h | 5 --- src/dolphindetailsview.cpp | 8 +++- src/dolphindetailsview.h | 1 + src/dolphiniconsview.cpp | 64 +++++++++++++++++++++++----- src/dolphiniconsview.h | 8 ++++ src/draganddrophelper.cpp | 85 +++++++++++++++++++++++++++++++++++++ src/draganddrophelper.h | 52 +++++++++++++++++++++++ src/sidebartreeview.cpp | 8 +++- src/sidebartreeview.h | 1 + 13 files changed, 224 insertions(+), 49 deletions(-) create mode 100644 src/draganddrophelper.cpp create mode 100644 src/draganddrophelper.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1cfbc9adf..c20251786 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,6 +12,7 @@ set(dolphinprivate_LIB_SRCS dolphiniconsview.cpp dolphincolumnview.cpp dolphincolumnwidget.cpp + draganddrophelper.cpp kcategorizedview.cpp kcategorydrawer.cpp dolphinmodel.cpp @@ -81,6 +82,7 @@ set(dolphin_SRCS dolphindirlister.cpp dolphincontextmenu.cpp dolphinsettingsdialog.cpp + draganddrophelper.cpp filterbar.cpp generalsettingspage.cpp generalviewsettingspage.cpp diff --git a/src/dolphincolumnwidget.cpp b/src/dolphincolumnwidget.cpp index 2dc3bc153..1a7f712f3 100644 --- a/src/dolphincolumnwidget.cpp +++ b/src/dolphincolumnwidget.cpp @@ -26,8 +26,8 @@ #include "dolphinmodel.h" #include "dolphinsortfilterproxymodel.h" #include "dolphinsettings.h" - #include "dolphin_columnmodesettings.h" +#include "draganddrophelper.h" #include #include @@ -197,6 +197,11 @@ void DolphinColumnWidget::setNameFilter(const QString& nameFilter) m_proxyModel->setFilterRegExp(nameFilter); } +void DolphinColumnWidget::startDrag(Qt::DropActions supportedActions) +{ + DragAndDropHelper::startDrag(this, supportedActions); +} + void DolphinColumnWidget::dragEnterEvent(QDragEnterEvent* event) { if (event->mimeData()->hasUrls()) { @@ -271,7 +276,7 @@ void DolphinColumnWidget::paintEvent(QPaintEvent* event) // TODO: remove this code when the issue #160611 is solved in Qt 4.4 if (m_dragging) { const QBrush& brush = m_viewOptions.palette.brush(QPalette::Normal, QPalette::Highlight); - DolphinController::drawHoverIndication(viewport(), m_dropRect, brush); + DragAndDropHelper::drawHoverIndication(viewport(), m_dropRect, brush); } } diff --git a/src/dolphincolumnwidget.h b/src/dolphincolumnwidget.h index fdb0471f2..e8fea3bf5 100644 --- a/src/dolphincolumnwidget.h +++ b/src/dolphincolumnwidget.h @@ -92,6 +92,7 @@ public: protected: virtual QStyleOptionViewItem viewOptions() const; + virtual void startDrag(Qt::DropActions supportedActions); virtual void dragEnterEvent(QDragEnterEvent* event); virtual void dragLeaveEvent(QDragLeaveEvent* event); virtual void dragMoveEvent(QDragMoveEvent* event); diff --git a/src/dolphincontroller.cpp b/src/dolphincontroller.cpp index 58f6f681f..f5fd5e836 100644 --- a/src/dolphincontroller.cpp +++ b/src/dolphincontroller.cpp @@ -19,8 +19,6 @@ #include "dolphincontroller.h" -#include - DolphinController::DolphinController(DolphinView* dolphinView) : QObject(dolphinView), m_zoomInPossible(false), @@ -98,33 +96,6 @@ void DolphinController::triggerZoomOut() emit zoomOut(); } -void DolphinController::drawHoverIndication(QWidget* widget, - const QRect& bounds, - const QBrush& brush) -{ - QPainter painter(widget); - painter.save(); - QBrush blendedBrush(brush); - QColor color = blendedBrush.color(); - color.setAlpha(64); - blendedBrush.setColor(color); - - const int radius = 10; - QPainterPath path(QPointF(bounds.left(), bounds.top() + radius)); - path.quadTo(bounds.left(), bounds.top(), bounds.left() + radius, bounds.top()); - path.lineTo(bounds.right() - radius, bounds.top()); - path.quadTo(bounds.right(), bounds.top(), bounds.right(), bounds.top() + radius); - path.lineTo(bounds.right(), bounds.bottom() - radius); - path.quadTo(bounds.right(), bounds.bottom(), bounds.right() - radius, bounds.bottom()); - path.lineTo(bounds.left() + radius, bounds.bottom()); - path.quadTo(bounds.left(), bounds.bottom(), bounds.left(), bounds.bottom() - radius); - path.closeSubpath(); - - painter.setRenderHint(QPainter::Antialiasing); - painter.fillPath(path, blendedBrush); - painter.restore(); -} - void DolphinController::triggerItem(const KFileItem& item) { emit itemTriggered(item); diff --git a/src/dolphincontroller.h b/src/dolphincontroller.h index 16b5f5587..e08e9e490 100644 --- a/src/dolphincontroller.h +++ b/src/dolphincontroller.h @@ -192,11 +192,6 @@ public: void setZoomOutPossible(bool possible); bool isZoomOutPossible() const; - // TODO: remove this method when the issue #160611 is solved in Qt 4.4 - static void drawHoverIndication(QWidget* widget, - const QRect& bounds, - const QBrush& brush); - public slots: /** * Emits the signal itemTriggered(). The method should be invoked by the diff --git a/src/dolphindetailsview.cpp b/src/dolphindetailsview.cpp index f4bba2f03..3fd1e9468 100644 --- a/src/dolphindetailsview.cpp +++ b/src/dolphindetailsview.cpp @@ -24,6 +24,7 @@ #include "dolphincontroller.h" #include "dolphinsettings.h" #include "dolphinsortfilterproxymodel.h" +#include "draganddrophelper.h" #include "viewproperties.h" #include "dolphin_detailsmodesettings.h" @@ -212,6 +213,11 @@ void DolphinDetailsView::mouseReleaseEvent(QMouseEvent* event) } } +void DolphinDetailsView::startDrag(Qt::DropActions supportedActions) +{ + DragAndDropHelper::startDrag(this, supportedActions); +} + void DolphinDetailsView::dragEnterEvent(QDragEnterEvent* event) { if (event->mimeData()->hasUrls()) { @@ -294,7 +300,7 @@ void DolphinDetailsView::paintEvent(QPaintEvent* event) // TODO: remove this code when the issue #160611 is solved in Qt 4.4 if (m_dragging) { const QBrush& brush = m_viewOptions.palette.brush(QPalette::Normal, QPalette::Highlight); - DolphinController::drawHoverIndication(viewport(), m_dropRect, brush); + DragAndDropHelper::drawHoverIndication(viewport(), m_dropRect, brush); } } diff --git a/src/dolphindetailsview.h b/src/dolphindetailsview.h index f00b263d1..1b21690c0 100644 --- a/src/dolphindetailsview.h +++ b/src/dolphindetailsview.h @@ -51,6 +51,7 @@ protected: virtual void mousePressEvent(QMouseEvent* event); virtual void mouseMoveEvent(QMouseEvent* event); virtual void mouseReleaseEvent(QMouseEvent* event); + virtual void startDrag(Qt::DropActions supportedActions); virtual void dragEnterEvent(QDragEnterEvent* event); virtual void dragLeaveEvent(QDragLeaveEvent* event); virtual void dragMoveEvent(QDragMoveEvent* event); diff --git a/src/dolphiniconsview.cpp b/src/dolphiniconsview.cpp index ea553c8be..c04a70fab 100644 --- a/src/dolphiniconsview.cpp +++ b/src/dolphiniconsview.cpp @@ -23,6 +23,7 @@ #include "dolphincontroller.h" #include "dolphinsettings.h" #include "dolphin_iconsmodesettings.h" +#include "draganddrophelper.h" #include #include @@ -45,7 +46,10 @@ DolphinIconsView::DolphinIconsView(QWidget* parent, DolphinController* controlle setViewMode(QListView::IconMode); setResizeMode(QListView::Adjust); setSpacing(KDialog::spacingHint()); - setMovement(QListView::Snap); + setMovement(QListView::Static); + setDragEnabled(true); + viewport()->setAcceptDrops(true); + setMouseTracking(true); viewport()->setAttribute(Qt::WA_Hover); @@ -138,12 +142,8 @@ QRect DolphinIconsView::visualRect(const QModelIndex& index) const itemRect.setHeight(maxHeight); } - KCategorizedSortFilterProxyModel* proxyModel = dynamic_cast(model()); - if (leftToRightFlow && !proxyModel->isCategorizedModel()) { - // TODO: This workaround bypasses a layout issue in QListView::visualRect(), where - // the horizontal position of items might get calculated in a wrong manner when the item - // name is too long. I'll try create a patch for Qt but as Dolphin must also work with - // Qt 4.3.0 this workaround must get applied at least for KDE 4.0. + if (leftToRightFlow && bypassVisualRectIssue()) { + // TODO: check inline comment inside bypassVisualRectIssue() for details const IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings(); const int margin = settings->gridSpacing(); const int gridWidth = gridSize().width(); @@ -178,6 +178,16 @@ void DolphinIconsView::mousePressEvent(QMouseEvent* event) KCategorizedView::mousePressEvent(event); } +void DolphinIconsView::startDrag(Qt::DropActions supportedActions) +{ + if (bypassVisualRectIssue()) { + // TODO: check inline comment inside bypassVisualRectIssue() for details + DragAndDropHelper::startDrag(this, supportedActions); + } else { + KCategorizedView::startDrag(supportedActions); + } +} + void DolphinIconsView::dragEnterEvent(QDragEnterEvent* event) { if (event->mimeData()->hasUrls()) { @@ -188,7 +198,12 @@ void DolphinIconsView::dragEnterEvent(QDragEnterEvent* event) void DolphinIconsView::dragLeaveEvent(QDragLeaveEvent* event) { - KCategorizedView::dragLeaveEvent(event); + if (bypassVisualRectIssue()) { + // TODO: check inline comment inside bypassVisualRectIssue() for details + QAbstractItemView::dragLeaveEvent(event); + } else { + KCategorizedView::dragLeaveEvent(event); + } // TODO: remove this code when the issue #160611 is solved in Qt 4.4 m_dragging = false; @@ -197,7 +212,12 @@ void DolphinIconsView::dragLeaveEvent(QDragLeaveEvent* event) void DolphinIconsView::dragMoveEvent(QDragMoveEvent* event) { - KCategorizedView::dragMoveEvent(event); + if (bypassVisualRectIssue()) { + // TODO: check inline comment inside bypassVisualRectIssue() for details + QAbstractItemView::dragMoveEvent(event); + } else { + KCategorizedView::dragMoveEvent(event); + } // TODO: remove this code when the issue #160611 is solved in Qt 4.4 const QModelIndex index = indexAt(event->pos()); @@ -224,7 +244,13 @@ void DolphinIconsView::dropEvent(QDropEvent* event) } } - KCategorizedView::dropEvent(event); + if (bypassVisualRectIssue()) { + // TODO: check inline comment inside bypassVisualRectIssue() for details + QAbstractItemView::dropEvent(event); + } else { + KCategorizedView::dropEvent(event); + } + m_dragging = false; } @@ -235,7 +261,7 @@ void DolphinIconsView::paintEvent(QPaintEvent* event) // TODO: remove this code when the issue #160611 is solved in Qt 4.4 if (m_dragging) { const QBrush& brush = m_viewOptions.palette.brush(QPalette::Normal, QPalette::Highlight); - DolphinController::drawHoverIndication(viewport(), m_dropRect, brush); + DragAndDropHelper::drawHoverIndication(viewport(), m_dropRect, brush); } } @@ -431,5 +457,21 @@ KFileItem DolphinIconsView::itemForIndex(const QModelIndex& index) const return dirModel->itemForIndex(dirIndex); } +bool DolphinIconsView::bypassVisualRectIssue() const +{ + // TODO: QListView::visualRect() calculates a wrong position of the items under + // certain circumstances (e. g. if the text is too long). This issue is bypassed + // inside DolphinIconsView::visualRect(), but internally QListView does not use + // visualRect() but the (non-virtual) QListView::rectForIndex(). This leads + // to problems in combination with drag & drop operations: visual fragments get + // created. To bypass the drag & drop issue the calls for QListView::dragMoveEvent(), + // QListView::dropEvent() are replaced by the QAbstractItemView counterparts and + // QAbstractItemView::startDrag() has been reimplemented. + // + // I'll try create a patch for Qt but as Dolphin must also work with + // Qt 4.3.0 this workaround must get applied at least for KDE 4.0. + KCategorizedSortFilterProxyModel* proxyModel = dynamic_cast(model()); + return !proxyModel->isCategorizedModel(); +} #include "dolphiniconsview.moc" diff --git a/src/dolphiniconsview.h b/src/dolphiniconsview.h index ae0a6299d..6c3f6fa38 100644 --- a/src/dolphiniconsview.h +++ b/src/dolphiniconsview.h @@ -54,6 +54,7 @@ protected: virtual QStyleOptionViewItem viewOptions() const; virtual void contextMenuEvent(QContextMenuEvent* event); virtual void mousePressEvent(QMouseEvent* event); + virtual void startDrag(Qt::DropActions supportedActions); virtual void dragEnterEvent(QDragEnterEvent* event); virtual void dragLeaveEvent(QDragLeaveEvent* event); virtual void dragMoveEvent(QDragMoveEvent* event); @@ -87,6 +88,13 @@ private: KFileItem itemForIndex(const QModelIndex& index) const; + /** + * Returns true, if the QListView-issue in QListView::visualRect() + * must be bypassed. TODO: this method is only temporary to have + * a usable drag & drop behavior until the issue in Qt is fixed. + */ + bool bypassVisualRectIssue() const; + private: DolphinController* m_controller; DolphinCategoryDrawer* m_categoryDrawer; diff --git a/src/draganddrophelper.cpp b/src/draganddrophelper.cpp new file mode 100644 index 000000000..d9188675a --- /dev/null +++ b/src/draganddrophelper.cpp @@ -0,0 +1,85 @@ +/*************************************************************************** + * Copyright (C) 2007 by Peter Penz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include "draganddrophelper.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +void DragAndDropHelper::startDrag(QAbstractItemView* itemView, Qt::DropActions supportedActions) +{ + QModelIndexList indexes = itemView->selectionModel()->selectedIndexes(); + if (indexes.count() > 0) { + QMimeData *data = itemView->model()->mimeData(indexes); + if (data == 0) { + return; + } + + QDrag* drag = new QDrag(itemView); + QPixmap pixmap; + if (indexes.count() == 1) { + QAbstractProxyModel* proxyModel = static_cast(itemView->model()); + KDirModel* dirModel = static_cast(proxyModel->sourceModel()); + const QModelIndex index = proxyModel->mapToSource(indexes.first()); + + const KFileItem item = dirModel->itemForIndex(index); + pixmap = item.pixmap(KIconLoader::SizeMedium, KIconLoader::SizeMedium); + } else { + pixmap = KIcon("item-drag-multiple").pixmap(KIconLoader::SizeMedium, KIconLoader::SizeMedium); + } + drag->setPixmap(pixmap); + drag->setMimeData(data); + drag->exec(supportedActions); + } +} + +void DragAndDropHelper::drawHoverIndication(QWidget* widget, + const QRect& bounds, + const QBrush& brush) +{ + QPainter painter(widget); + painter.save(); + QBrush blendedBrush(brush); + QColor color = blendedBrush.color(); + color.setAlpha(64); + blendedBrush.setColor(color); + + const int radius = 10; + QPainterPath path(QPointF(bounds.left(), bounds.top() + radius)); + path.quadTo(bounds.left(), bounds.top(), bounds.left() + radius, bounds.top()); + path.lineTo(bounds.right() - radius, bounds.top()); + path.quadTo(bounds.right(), bounds.top(), bounds.right(), bounds.top() + radius); + path.lineTo(bounds.right(), bounds.bottom() - radius); + path.quadTo(bounds.right(), bounds.bottom(), bounds.right() - radius, bounds.bottom()); + path.lineTo(bounds.left() + radius, bounds.bottom()); + path.quadTo(bounds.left(), bounds.bottom(), bounds.left(), bounds.bottom() - radius); + path.closeSubpath(); + + painter.setRenderHint(QPainter::Antialiasing); + painter.fillPath(path, blendedBrush); + painter.restore(); +} diff --git a/src/draganddrophelper.h b/src/draganddrophelper.h new file mode 100644 index 000000000..9e174959b --- /dev/null +++ b/src/draganddrophelper.h @@ -0,0 +1,52 @@ +/*************************************************************************** + * Copyright (C) 2007 by Peter Penz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef DRAGANDDROPHELPER_H +#define DRAGANDDROPHELPER_H + +#include + +class QAbstractItemView; +class QBrush; +class QRect; +class QWidget; + +/** + * @brief Helper class to bypass some drag & drop limitations in Qt. + * + * The class is used by DolphinIconsView, DolphinDetailsView, + * DolphinColumnView and SidebarTreeView to have a consistent + * drag and drop behavior between all views. + */ +class DragAndDropHelper +{ + +public: + /** + * Creates a drag object for the view \a itemView for all selected items. + */ + static void startDrag(QAbstractItemView* itemView, Qt::DropActions supportedActions); + + // TODO: remove this method when the issue #160611 is solved in Qt 4.4 + static void drawHoverIndication(QWidget* widget, + const QRect& bounds, + const QBrush& brush); +}; + +#endif diff --git a/src/sidebartreeview.cpp b/src/sidebartreeview.cpp index ae6c26224..3567c35d6 100644 --- a/src/sidebartreeview.cpp +++ b/src/sidebartreeview.cpp @@ -21,6 +21,7 @@ #include "dolphincontroller.h" #include "dolphinmodel.h" +#include "draganddrophelper.h" #include #include @@ -95,6 +96,11 @@ bool SidebarTreeView::event(QEvent* event) return QTreeView::event(event); } +void SidebarTreeView::startDrag(Qt::DropActions supportedActions) +{ + DragAndDropHelper::startDrag(this, supportedActions); +} + void SidebarTreeView::dragEnterEvent(QDragEnterEvent* event) { if (event->mimeData()->hasUrls()) { @@ -146,7 +152,7 @@ void SidebarTreeView::paintEvent(QPaintEvent* event) // TODO: remove this code when the issue #160611 is solved in Qt 4.4 if (m_dragging) { const QBrush& brush = palette().brush(QPalette::Normal, QPalette::Highlight); - DolphinController::drawHoverIndication(viewport(), m_dropRect, brush); + DragAndDropHelper::drawHoverIndication(viewport(), m_dropRect, brush); } } diff --git a/src/sidebartreeview.h b/src/sidebartreeview.h index ba8fd7485..b2e42e24f 100644 --- a/src/sidebartreeview.h +++ b/src/sidebartreeview.h @@ -46,6 +46,7 @@ signals: protected: virtual bool event(QEvent* event); + virtual void startDrag(Qt::DropActions supportedActions); virtual void dragEnterEvent(QDragEnterEvent* event); virtual void dragLeaveEvent(QDragLeaveEvent* event); virtual void dragMoveEvent(QDragMoveEvent* event); -- 2.47.3