mirror of
https://invent.kde.org/system/dolphin
synced 2024-11-05 18:47:12 +00:00
Improved drag and drop support
This commit is contained in:
parent
8266e456a1
commit
7a91492cff
11 changed files with 186 additions and 248 deletions
|
@ -49,6 +49,7 @@ set(dolphinprivate_LIB_SRCS
|
||||||
views/dolphinremoteencoding.cpp
|
views/dolphinremoteencoding.cpp
|
||||||
views/dolphinviewactionhandler.cpp
|
views/dolphinviewactionhandler.cpp
|
||||||
views/dolphinviewautoscroller.cpp
|
views/dolphinviewautoscroller.cpp
|
||||||
|
views/draganddrophelper.cpp
|
||||||
views/folderexpander.cpp
|
views/folderexpander.cpp
|
||||||
views/renamedialog.cpp
|
views/renamedialog.cpp
|
||||||
views/tooltips/filemetadatatooltip.cpp
|
views/tooltips/filemetadatatooltip.cpp
|
||||||
|
|
|
@ -123,24 +123,6 @@ bool KFileItemModel::setData(int index, const QHash<QByteArray, QVariant>& value
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int KFileItemModel::indexForKeyboardSearch(const QString& text, int startFromIndex) const
|
|
||||||
{
|
|
||||||
startFromIndex = qMax(0, startFromIndex);
|
|
||||||
for (int i = startFromIndex; i < count(); i++) {
|
|
||||||
if (data(i)["name"].toString().startsWith(text, Qt::CaseInsensitive)) {
|
|
||||||
kDebug() << data(i)["name"].toString();
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < startFromIndex; i++) {
|
|
||||||
if (data(i)["name"].toString().startsWith(text, Qt::CaseInsensitive)) {
|
|
||||||
kDebug() << data(i)["name"].toString();
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KFileItemModel::supportsGrouping() const
|
bool KFileItemModel::supportsGrouping() const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -189,6 +171,30 @@ QMimeData* KFileItemModel::createMimeData(const QSet<int>& indexes) const
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int KFileItemModel::indexForKeyboardSearch(const QString& text, int startFromIndex) const
|
||||||
|
{
|
||||||
|
startFromIndex = qMax(0, startFromIndex);
|
||||||
|
for (int i = startFromIndex; i < count(); i++) {
|
||||||
|
if (data(i)["name"].toString().startsWith(text, Qt::CaseInsensitive)) {
|
||||||
|
kDebug() << data(i)["name"].toString();
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < startFromIndex; i++) {
|
||||||
|
if (data(i)["name"].toString().startsWith(text, Qt::CaseInsensitive)) {
|
||||||
|
kDebug() << data(i)["name"].toString();
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KFileItemModel::supportsDropping(int index) const
|
||||||
|
{
|
||||||
|
const KFileItem item = fileItem(index);
|
||||||
|
return item.isNull() ? false : item.isDir();
|
||||||
|
}
|
||||||
|
|
||||||
KFileItem KFileItemModel::fileItem(int index) const
|
KFileItem KFileItemModel::fileItem(int index) const
|
||||||
{
|
{
|
||||||
if (index >= 0 && index < count()) {
|
if (index >= 0 && index < count()) {
|
||||||
|
|
|
@ -54,10 +54,6 @@ public:
|
||||||
virtual QHash<QByteArray, QVariant> data(int index) const;
|
virtual QHash<QByteArray, QVariant> data(int index) const;
|
||||||
virtual bool setData(int index, const QHash<QByteArray, QVariant> &values);
|
virtual bool setData(int index, const QHash<QByteArray, QVariant> &values);
|
||||||
|
|
||||||
/**
|
|
||||||
* @reimp
|
|
||||||
*/
|
|
||||||
virtual int indexForKeyboardSearch(const QString& text, int startFromIndex = 0) const;
|
|
||||||
/**
|
/**
|
||||||
* @return True
|
* @return True
|
||||||
* @reimp
|
* @reimp
|
||||||
|
@ -73,6 +69,12 @@ public:
|
||||||
/** @reimp */
|
/** @reimp */
|
||||||
virtual QMimeData* createMimeData(const QSet<int>& indexes) const;
|
virtual QMimeData* createMimeData(const QSet<int>& indexes) const;
|
||||||
|
|
||||||
|
/** @reimp */
|
||||||
|
virtual int indexForKeyboardSearch(const QString& text, int startFromIndex = 0) const;
|
||||||
|
|
||||||
|
/** @reimp */
|
||||||
|
virtual bool supportsDropping(int index) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The file-item for the index \a index. If the index is in a valid
|
* @return The file-item for the index \a index. If the index is in a valid
|
||||||
* range it is assured that the file-item is not null. The runtime
|
* range it is assured that the file-item is not null. The runtime
|
||||||
|
|
|
@ -482,18 +482,45 @@ bool KItemListController::dragLeaveEvent(QGraphicsSceneDragDropEvent* event, con
|
||||||
|
|
||||||
bool KItemListController::dragMoveEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform)
|
bool KItemListController::dragMoveEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform)
|
||||||
{
|
{
|
||||||
Q_UNUSED(event);
|
|
||||||
Q_UNUSED(transform);
|
Q_UNUSED(transform);
|
||||||
|
if (!m_model || !m_view) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
KItemListWidget* oldHoveredWidget = hoveredWidget();
|
||||||
|
KItemListWidget* newHoveredWidget = widgetForPos(event->pos());
|
||||||
|
if (oldHoveredWidget != newHoveredWidget) {
|
||||||
|
if (oldHoveredWidget) {
|
||||||
|
oldHoveredWidget->setHovered(false);
|
||||||
|
emit itemUnhovered(oldHoveredWidget->index());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newHoveredWidget) {
|
||||||
|
const int index = newHoveredWidget->index();
|
||||||
|
if (m_model->supportsDropping(index)) {
|
||||||
|
newHoveredWidget->setHovered(true);
|
||||||
|
}
|
||||||
|
emit itemHovered(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KItemListController::dropEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform)
|
bool KItemListController::dropEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform)
|
||||||
{
|
{
|
||||||
Q_UNUSED(event);
|
Q_UNUSED(transform)
|
||||||
Q_UNUSED(transform);
|
if (!m_view) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QPointF pos = transform.map(event->pos());
|
||||||
|
const int index = m_view->itemAt(pos);
|
||||||
|
emit itemDropEvent(index, event);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool KItemListController::hoverEnterEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform)
|
bool KItemListController::hoverEnterEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform)
|
||||||
{
|
{
|
||||||
Q_UNUSED(event);
|
Q_UNUSED(event);
|
||||||
|
@ -503,46 +530,22 @@ bool KItemListController::hoverEnterEvent(QGraphicsSceneHoverEvent* event, const
|
||||||
|
|
||||||
bool KItemListController::hoverMoveEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform)
|
bool KItemListController::hoverMoveEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform)
|
||||||
{
|
{
|
||||||
// The implementation assumes that only one item can get hovered no matter
|
|
||||||
// whether they overlap or not.
|
|
||||||
|
|
||||||
Q_UNUSED(transform);
|
Q_UNUSED(transform);
|
||||||
if (!m_model || !m_view) {
|
if (!m_model || !m_view) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search the previously hovered item that might get unhovered
|
KItemListWidget* oldHoveredWidget = hoveredWidget();
|
||||||
KItemListWidget* unhoveredWidget = 0;
|
KItemListWidget* newHoveredWidget = widgetForPos(event->pos());
|
||||||
foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) {
|
if (oldHoveredWidget != newHoveredWidget) {
|
||||||
if (widget->isHovered()) {
|
if (oldHoveredWidget) {
|
||||||
unhoveredWidget = widget;
|
oldHoveredWidget->setHovered(false);
|
||||||
break;
|
emit itemUnhovered(oldHoveredWidget->index());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search the currently hovered item
|
if (newHoveredWidget) {
|
||||||
KItemListWidget* hoveredWidget = 0;
|
newHoveredWidget->setHovered(true);
|
||||||
foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) {
|
emit itemHovered(newHoveredWidget->index());
|
||||||
const QPointF mappedPos = widget->mapFromItem(m_view, event->pos());
|
|
||||||
|
|
||||||
const bool hovered = widget->contains(mappedPos) &&
|
|
||||||
!widget->expansionToggleRect().contains(mappedPos) &&
|
|
||||||
!widget->selectionToggleRect().contains(mappedPos);
|
|
||||||
if (hovered) {
|
|
||||||
hoveredWidget = widget;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unhoveredWidget != hoveredWidget) {
|
|
||||||
if (unhoveredWidget) {
|
|
||||||
unhoveredWidget->setHovered(false);
|
|
||||||
emit itemUnhovered(unhoveredWidget->index());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hoveredWidget) {
|
|
||||||
hoveredWidget->setHovered(true);
|
|
||||||
emit itemHovered(hoveredWidget->index());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -755,4 +758,35 @@ void KItemListController::startDragging()
|
||||||
drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction, Qt::IgnoreAction);
|
drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction, Qt::IgnoreAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KItemListWidget* KItemListController::hoveredWidget() const
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_view);
|
||||||
|
|
||||||
|
foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) {
|
||||||
|
if (widget->isHovered()) {
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
KItemListWidget* KItemListController::widgetForPos(const QPointF& pos) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_view);
|
||||||
|
|
||||||
|
foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) {
|
||||||
|
const QPointF mappedPos = widget->mapFromItem(m_view, pos);
|
||||||
|
|
||||||
|
const bool hovered = widget->contains(mappedPos) &&
|
||||||
|
!widget->expansionToggleRect().contains(mappedPos) &&
|
||||||
|
!widget->selectionToggleRect().contains(mappedPos);
|
||||||
|
if (hovered) {
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#include "kitemlistcontroller.moc"
|
#include "kitemlistcontroller.moc"
|
||||||
|
|
|
@ -34,6 +34,7 @@ class KItemModelBase;
|
||||||
class KItemListKeyboardSearchManager;
|
class KItemListKeyboardSearchManager;
|
||||||
class KItemListSelectionManager;
|
class KItemListSelectionManager;
|
||||||
class KItemListView;
|
class KItemListView;
|
||||||
|
class KItemListWidget;
|
||||||
class QGraphicsSceneHoverEvent;
|
class QGraphicsSceneHoverEvent;
|
||||||
class QGraphicsSceneDragDropEvent;
|
class QGraphicsSceneDragDropEvent;
|
||||||
class QGraphicsSceneMouseEvent;
|
class QGraphicsSceneMouseEvent;
|
||||||
|
@ -113,6 +114,7 @@ signals:
|
||||||
* Is emitted if the item with the index \p index gets hovered.
|
* Is emitted if the item with the index \p index gets hovered.
|
||||||
*/
|
*/
|
||||||
void itemHovered(int index);
|
void itemHovered(int index);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is emitted if the item with the index \p index gets unhovered.
|
* Is emitted if the item with the index \p index gets unhovered.
|
||||||
* It is assured that the signal itemHovered() for this index
|
* It is assured that the signal itemHovered() for this index
|
||||||
|
@ -122,6 +124,13 @@ signals:
|
||||||
|
|
||||||
void itemExpansionToggleClicked(int index);
|
void itemExpansionToggleClicked(int index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is emitted if a drop event is done above the item with the index
|
||||||
|
* \a index. If \a index is < 0 the drop event is done above an
|
||||||
|
* empty area of the view.
|
||||||
|
*/
|
||||||
|
void itemDropEvent(int index, QGraphicsSceneDragDropEvent* event);
|
||||||
|
|
||||||
void modelChanged(KItemModelBase* current, KItemModelBase* previous);
|
void modelChanged(KItemModelBase* current, KItemModelBase* previous);
|
||||||
void viewChanged(KItemListView* current, KItemListView* previous);
|
void viewChanged(KItemListView* current, KItemListView* previous);
|
||||||
|
|
||||||
|
@ -142,6 +151,18 @@ private:
|
||||||
*/
|
*/
|
||||||
void startDragging();
|
void startDragging();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Widget that is currently in the hovered state. 0 is returned
|
||||||
|
* if no widget is marked as hovered.
|
||||||
|
*/
|
||||||
|
KItemListWidget* hoveredWidget() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Widget that is below the position \a pos. 0 is returned
|
||||||
|
* if no widget is below the position.
|
||||||
|
*/
|
||||||
|
KItemListWidget* widgetForPos(const QPointF& pos) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SelectionBehavior m_selectionBehavior;
|
SelectionBehavior m_selectionBehavior;
|
||||||
KItemModelBase* m_model;
|
KItemModelBase* m_model;
|
||||||
|
|
|
@ -116,6 +116,12 @@ int KItemModelBase::indexForKeyboardSearch(const QString& text, int startFromInd
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool KItemModelBase::supportsDropping(int index) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(index);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void KItemModelBase::onGroupRoleChanged(const QByteArray& current, const QByteArray& previous)
|
void KItemModelBase::onGroupRoleChanged(const QByteArray& current, const QByteArray& previous)
|
||||||
{
|
{
|
||||||
Q_UNUSED(current);
|
Q_UNUSED(current);
|
||||||
|
|
|
@ -123,6 +123,20 @@ public:
|
||||||
* @param startFromIndex the index from which to start searching from
|
* @param startFromIndex the index from which to start searching from
|
||||||
*/
|
*/
|
||||||
virtual int indexForKeyboardSearch(const QString& text, int startFromIndex = 0) const;
|
virtual int indexForKeyboardSearch(const QString& text, int startFromIndex = 0) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return True, if the item with the index \a index basically supports dropping.
|
||||||
|
* Per default false is returned.
|
||||||
|
*
|
||||||
|
* The information is used only to give a visual feedback during a drag operation
|
||||||
|
* and not to decide whether a drop event gets emitted. It is it is still up to
|
||||||
|
* the receiver of KItemListController::itemDropEvent() to decide how to handle
|
||||||
|
* the drop event.
|
||||||
|
*/
|
||||||
|
// TODO: Should the MIME-data be passed too so that the model can do a more specific
|
||||||
|
// decision whether it accepts the drop?
|
||||||
|
virtual bool supportsDropping(int index) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**
|
/**
|
||||||
* Is emitted if one or more items have been inserted. Each item-range consists
|
* Is emitted if one or more items have been inserted. Each item-range consists
|
||||||
|
|
|
@ -22,10 +22,12 @@
|
||||||
|
|
||||||
#include <QAbstractItemView>
|
#include <QAbstractItemView>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QBoxLayout>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
|
#include <QDropEvent>
|
||||||
|
#include <QGraphicsSceneDragDropEvent>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
#include <QItemSelection>
|
#include <QItemSelection>
|
||||||
#include <QBoxLayout>
|
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
|
|
||||||
|
@ -60,6 +62,7 @@
|
||||||
#include "dolphin_detailsmodesettings.h"
|
#include "dolphin_detailsmodesettings.h"
|
||||||
#include "dolphin_generalsettings.h"
|
#include "dolphin_generalsettings.h"
|
||||||
#include "dolphinitemlistcontainer.h"
|
#include "dolphinitemlistcontainer.h"
|
||||||
|
#include "draganddrophelper.h"
|
||||||
#include "renamedialog.h"
|
#include "renamedialog.h"
|
||||||
#include "settings/dolphinsettings.h"
|
#include "settings/dolphinsettings.h"
|
||||||
#include "viewmodecontroller.h"
|
#include "viewmodecontroller.h"
|
||||||
|
@ -172,6 +175,7 @@ DolphinView::DolphinView(const KUrl& url, QWidget* parent) :
|
||||||
connect(controller, SIGNAL(itemExpansionToggleClicked(int)), this, SLOT(slotItemExpansionToggleClicked(int)));
|
connect(controller, SIGNAL(itemExpansionToggleClicked(int)), this, SLOT(slotItemExpansionToggleClicked(int)));
|
||||||
connect(controller, SIGNAL(itemHovered(int)), this, SLOT(slotItemHovered(int)));
|
connect(controller, SIGNAL(itemHovered(int)), this, SLOT(slotItemHovered(int)));
|
||||||
connect(controller, SIGNAL(itemUnhovered(int)), this, SLOT(slotItemUnhovered(int)));
|
connect(controller, SIGNAL(itemUnhovered(int)), this, SLOT(slotItemUnhovered(int)));
|
||||||
|
connect(controller, SIGNAL(itemDropEvent(int,QGraphicsSceneDragDropEvent*)), this, SLOT(slotItemDropEvent(int,QGraphicsSceneDragDropEvent*)));
|
||||||
|
|
||||||
KItemListSelectionManager* selectionManager = controller->selectionManager();
|
KItemListSelectionManager* selectionManager = controller->selectionManager();
|
||||||
connect(selectionManager, SIGNAL(selectionChanged(QSet<int>,QSet<int>)),
|
connect(selectionManager, SIGNAL(selectionChanged(QSet<int>,QSet<int>)),
|
||||||
|
@ -776,6 +780,19 @@ void DolphinView::slotItemUnhovered(int index)
|
||||||
emit requestItemInfo(KFileItem());
|
emit requestItemInfo(KFileItem());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DolphinView::slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* event)
|
||||||
|
{
|
||||||
|
const KFileItem destItem = fileItemModel()->fileItem(index);
|
||||||
|
|
||||||
|
QDropEvent dropEvent(event->pos().toPoint(),
|
||||||
|
event->possibleActions(),
|
||||||
|
event->mimeData(),
|
||||||
|
event->buttons(),
|
||||||
|
event->modifiers());
|
||||||
|
|
||||||
|
DragAndDropHelper::dropUrls(destItem, url(), &dropEvent, this);
|
||||||
|
}
|
||||||
|
|
||||||
void DolphinView::slotSelectionChanged(const QSet<int>& current, const QSet<int>& previous)
|
void DolphinView::slotSelectionChanged(const QSet<int>& current, const QSet<int>& previous)
|
||||||
{
|
{
|
||||||
const int currentCount = current.count();
|
const int currentCount = current.count();
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
#ifndef DOLPHINVIEW_H
|
#ifndef DOLPHINVIEW_H
|
||||||
#define DOLPHINVIEW_H
|
#define DOLPHINVIEW_H
|
||||||
|
|
||||||
|
@ -48,6 +47,7 @@ class KFileItemModel;
|
||||||
class KUrl;
|
class KUrl;
|
||||||
class ToolTipManager;
|
class ToolTipManager;
|
||||||
class ViewProperties;
|
class ViewProperties;
|
||||||
|
class QGraphicsSceneDragDropEvent;
|
||||||
class QRegExp;
|
class QRegExp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -559,6 +559,7 @@ private slots:
|
||||||
void slotItemExpansionToggleClicked(int index);
|
void slotItemExpansionToggleClicked(int index);
|
||||||
void slotItemHovered(int index);
|
void slotItemHovered(int index);
|
||||||
void slotItemUnhovered(int index);
|
void slotItemUnhovered(int index);
|
||||||
|
void slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* event);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emits the signal \a selectionChanged() with a small delay. This is
|
* Emits the signal \a selectionChanged() with a small delay. This is
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Copyright (C) 2007 by Peter Penz <peter.penz19@gmail.com> *
|
* Copyright (C) 2007-2011 by Peter Penz <peter.penz19@gmail.com> *
|
||||||
* Copyright (C) 2007 by David Faure <faure@kde.org> *
|
* Copyright (C) 2007 by David Faure <faure@kde.org> *
|
||||||
* *
|
* *
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
@ -20,73 +20,15 @@
|
||||||
|
|
||||||
#include "draganddrophelper.h"
|
#include "draganddrophelper.h"
|
||||||
|
|
||||||
#include <KDirModel>
|
|
||||||
#include <KFileItem>
|
#include <KFileItem>
|
||||||
#include <KIcon>
|
|
||||||
#include <KLocale>
|
#include <KLocale>
|
||||||
#include <konq_operations.h>
|
#include <konq_operations.h>
|
||||||
|
#include <KUrl>
|
||||||
#include "views/dolphiniconsview.h"
|
|
||||||
#include "views/dolphinviewcontroller.h"
|
|
||||||
|
|
||||||
#include <QAbstractItemView>
|
|
||||||
#include <QAbstractProxyModel>
|
|
||||||
#include <QtDBus>
|
#include <QtDBus>
|
||||||
#include <QDrag>
|
#include <QDropEvent>
|
||||||
#include <QPainter>
|
#include <QWidget>
|
||||||
|
|
||||||
class DragAndDropHelperSingleton
|
QString DragAndDropHelper::dropUrls(const KFileItem& destItem,
|
||||||
{
|
|
||||||
public:
|
|
||||||
DragAndDropHelper instance;
|
|
||||||
};
|
|
||||||
K_GLOBAL_STATIC(DragAndDropHelperSingleton, s_dragAndDropHelper)
|
|
||||||
|
|
||||||
DragAndDropHelper& DragAndDropHelper::instance()
|
|
||||||
{
|
|
||||||
return s_dragAndDropHelper->instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DragAndDropHelper::startDrag(QAbstractItemView* itemView,
|
|
||||||
Qt::DropActions supportedActions,
|
|
||||||
DolphinViewController* dolphinViewController)
|
|
||||||
{
|
|
||||||
// Do not start a new drag until the previous one has been finished.
|
|
||||||
// This is a (possibly temporary) fix for bug #187884.
|
|
||||||
static bool isDragging = false;
|
|
||||||
if (isDragging) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
isDragging = true;
|
|
||||||
|
|
||||||
const QModelIndexList indexes = itemView->selectionModel()->selectedIndexes();
|
|
||||||
if (!indexes.isEmpty()) {
|
|
||||||
QMimeData *data = itemView->model()->mimeData(indexes);
|
|
||||||
if (!data) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dolphinViewController) {
|
|
||||||
dolphinViewController->requestToolTipHiding();
|
|
||||||
}
|
|
||||||
|
|
||||||
QDrag* drag = new QDrag(itemView);
|
|
||||||
drag->setPixmap(createDragPixmap(itemView));
|
|
||||||
drag->setMimeData(data);
|
|
||||||
|
|
||||||
m_dragSource = itemView;
|
|
||||||
drag->exec(supportedActions, Qt::IgnoreAction);
|
|
||||||
m_dragSource = 0;
|
|
||||||
}
|
|
||||||
isDragging = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DragAndDropHelper::isDragSource(QAbstractItemView* itemView) const
|
|
||||||
{
|
|
||||||
return m_dragSource && (m_dragSource == itemView);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DragAndDropHelper::dropUrls(const KFileItem& destItem,
|
|
||||||
const KUrl& destPath,
|
const KUrl& destPath,
|
||||||
QDropEvent* event,
|
QDropEvent* event,
|
||||||
QWidget* widget)
|
QWidget* widget)
|
||||||
|
@ -96,7 +38,7 @@ void DragAndDropHelper::dropUrls(const KFileItem& destItem,
|
||||||
|
|
||||||
const QMimeData* mimeData = event->mimeData();
|
const QMimeData* mimeData = event->mimeData();
|
||||||
if (mimeData->hasFormat("application/x-kde-dndextract")) {
|
if (mimeData->hasFormat("application/x-kde-dndextract")) {
|
||||||
QString remoteDBusClient = mimeData->data("application/x-kde-dndextract");
|
const QString remoteDBusClient = mimeData->data("application/x-kde-dndextract");
|
||||||
QDBusMessage message = QDBusMessage::createMethodCall(remoteDBusClient, "/DndExtract",
|
QDBusMessage message = QDBusMessage::createMethodCall(remoteDBusClient, "/DndExtract",
|
||||||
"org.kde.DndExtract", "extractSelectedFilesTo");
|
"org.kde.DndExtract", "extractSelectedFilesTo");
|
||||||
message.setArguments(QVariantList() << destination.pathOrUrl());
|
message.setArguments(QVariantList() << destination.pathOrUrl());
|
||||||
|
@ -104,79 +46,15 @@ void DragAndDropHelper::dropUrls(const KFileItem& destItem,
|
||||||
} else {
|
} else {
|
||||||
const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData());
|
const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData());
|
||||||
const int urlsCount = urls.count();
|
const int urlsCount = urls.count();
|
||||||
if ((urlsCount == 1) && (urls.first() == destination)) {
|
if (urlsCount == 1 && urls.first() == destination) {
|
||||||
emit errorMessage(i18nc("@info:status", "A folder cannot be dropped into itself"));
|
return i18nc("@info:status", "A folder cannot be dropped into itself");
|
||||||
} else if (dropToItem) {
|
} else if (dropToItem) {
|
||||||
KonqOperations::doDrop(destItem, destination, event, widget);
|
KonqOperations::doDrop(destItem, destination, event, widget);
|
||||||
} else {
|
} else {
|
||||||
KonqOperations::doDrop(KFileItem(), destination, event, widget);
|
KonqOperations::doDrop(KFileItem(), destination, event, widget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
DragAndDropHelper::DragAndDropHelper()
|
|
||||||
: m_dragSource(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QPixmap DragAndDropHelper::createDragPixmap(QAbstractItemView* itemView) const
|
|
||||||
{
|
|
||||||
const QModelIndexList selectedIndexes = itemView->selectionModel()->selectedIndexes();
|
|
||||||
Q_ASSERT(!selectedIndexes.isEmpty());
|
|
||||||
|
|
||||||
QAbstractProxyModel* proxyModel = static_cast<QAbstractProxyModel*>(itemView->model());
|
|
||||||
KDirModel* dirModel = static_cast<KDirModel*>(proxyModel->sourceModel());
|
|
||||||
|
|
||||||
const int itemCount = selectedIndexes.count();
|
|
||||||
|
|
||||||
// If more than one item is dragged, align the items inside a
|
|
||||||
// rectangular grid. The maximum grid size is limited to 5 x 5 items.
|
|
||||||
int xCount = 3;
|
|
||||||
int size = KIconLoader::SizeMedium;
|
|
||||||
if (itemCount > 16) {
|
|
||||||
xCount = 5;
|
|
||||||
size = KIconLoader::SizeSmall;
|
|
||||||
} else if (itemCount > 9) {
|
|
||||||
xCount = 4;
|
|
||||||
size = KIconLoader::SizeSmallMedium;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (itemCount < xCount) {
|
|
||||||
xCount = itemCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
int yCount = itemCount / xCount;
|
|
||||||
if (itemCount % xCount != 0) {
|
|
||||||
++yCount;
|
|
||||||
}
|
|
||||||
if (yCount > xCount) {
|
|
||||||
yCount = xCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw the selected items into the grid cells
|
|
||||||
QPixmap dragPixmap(xCount * size + xCount - 1, yCount * size + yCount - 1);
|
|
||||||
dragPixmap.fill(Qt::transparent);
|
|
||||||
|
|
||||||
QPainter painter(&dragPixmap);
|
|
||||||
int x = 0;
|
|
||||||
int y = 0;
|
|
||||||
foreach (const QModelIndex& selectedIndex, selectedIndexes) {
|
|
||||||
const QModelIndex index = proxyModel->mapToSource(selectedIndex);
|
|
||||||
const KFileItem item = dirModel->itemForIndex(index);
|
|
||||||
const QPixmap pixmap = item.pixmap(size, size);
|
|
||||||
painter.drawPixmap(x, y, pixmap);
|
|
||||||
|
|
||||||
x += size + 1;
|
|
||||||
if (x >= dragPixmap.width()) {
|
|
||||||
x = 0;
|
|
||||||
y += size + 1;
|
|
||||||
}
|
|
||||||
if (y >= dragPixmap.height()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dragPixmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "draganddrophelper.moc"
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Copyright (C) 2007 by Peter Penz <peter.penz19@gmail.com> *
|
* Copyright (C) 2007-2011 by Peter Penz <peter.penz19@gmail.com> *
|
||||||
* Copyright (C) 2007 by David Faure <faure@kde.org> *
|
* Copyright (C) 2007 by David Faure <faure@kde.org> *
|
||||||
* *
|
* *
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
@ -22,44 +22,17 @@
|
||||||
#define DRAGANDDROPHELPER_H
|
#define DRAGANDDROPHELPER_H
|
||||||
|
|
||||||
#include "libdolphin_export.h"
|
#include "libdolphin_export.h"
|
||||||
#include <QObject>
|
|
||||||
#include <QPixmap>
|
|
||||||
|
|
||||||
class DolphinViewController;
|
#include <QString>
|
||||||
|
|
||||||
class KFileItem;
|
class KFileItem;
|
||||||
class KUrl;
|
class KUrl;
|
||||||
class QDropEvent;
|
class QDropEvent;
|
||||||
class QAbstractItemView;
|
|
||||||
class QMimeData;
|
|
||||||
class QWidget;
|
class QWidget;
|
||||||
|
|
||||||
/**
|
class LIBDOLPHINPRIVATE_EXPORT DragAndDropHelper
|
||||||
* @brief Helper class for having a common drag and drop behavior.
|
|
||||||
*
|
|
||||||
* The class is used by DolphinIconsView, DolphinDetailsView,
|
|
||||||
* DolphinColumnView and PanelTreeView to have a consistent
|
|
||||||
* drag and drop behavior between all views.
|
|
||||||
*/
|
|
||||||
class LIBDOLPHINPRIVATE_EXPORT DragAndDropHelper : public QObject
|
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static DragAndDropHelper& instance();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a drag object for the view \a itemView for all selected items.
|
|
||||||
*/
|
|
||||||
void startDrag(QAbstractItemView* itemView,
|
|
||||||
Qt::DropActions supportedActions,
|
|
||||||
DolphinViewController* dolphinViewController = 0);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if and only if the view \a itemView was the last view to
|
|
||||||
* be passed to startDrag(...), and that drag is still in progress.
|
|
||||||
*/
|
|
||||||
bool isDragSource(QAbstractItemView* itemView) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the dropping of URLs to the given
|
* Handles the dropping of URLs to the given
|
||||||
* destination. A context menu with the options
|
* destination. A context menu with the options
|
||||||
|
@ -69,28 +42,13 @@ public:
|
||||||
* @param destPath Path of the destination.
|
* @param destPath Path of the destination.
|
||||||
* @param event Drop event.
|
* @param event Drop event.
|
||||||
* @param widget Source widget where the dragging has been started.
|
* @param widget Source widget where the dragging has been started.
|
||||||
|
* @return Error message if dropping is not possible. If an empty string
|
||||||
|
* is returned, the dropping has been successful.
|
||||||
*/
|
*/
|
||||||
void dropUrls(const KFileItem& destItem,
|
static QString dropUrls(const KFileItem& destItem,
|
||||||
const KUrl& destPath,
|
const KUrl& destPath,
|
||||||
QDropEvent* event,
|
QDropEvent* event,
|
||||||
QWidget* widget);
|
QWidget* widget);
|
||||||
signals:
|
|
||||||
void errorMessage(const QString& msg);
|
|
||||||
|
|
||||||
private:
|
|
||||||
DragAndDropHelper();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a pixmap the contains the all icons of the items
|
|
||||||
* that are dragged.
|
|
||||||
*/
|
|
||||||
QPixmap createDragPixmap(QAbstractItemView* itemView) const;
|
|
||||||
|
|
||||||
// The last view passed in startDrag(...), or 0 if
|
|
||||||
// no startDrag(...) initiated drag is in progress.
|
|
||||||
QAbstractItemView *m_dragSource;
|
|
||||||
|
|
||||||
friend class DragAndDropHelperSingleton;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue