views/dolphinremoteencoding.cpp
views/dolphinviewactionhandler.cpp
views/dolphinviewautoscroller.cpp
+ views/draganddrophelper.cpp
views/folderexpander.cpp
views/renamedialog.cpp
views/tooltips/filemetadatatooltip.cpp
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
{
return true;
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
{
if (index >= 0 && index < count()) {
virtual QHash<QByteArray, QVariant> data(int index) const;
virtual bool setData(int index, const QHash<QByteArray, QVariant> &values);
- /**
- * @reimp
- */
- virtual int indexForKeyboardSearch(const QString& text, int startFromIndex = 0) const;
/**
* @return True
* @reimp
/** @reimp */
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
* range it is assured that the file-item is not null. The runtime
bool KItemListController::dragMoveEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform)
{
- Q_UNUSED(event);
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;
}
bool KItemListController::dropEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform)
{
- Q_UNUSED(event);
- Q_UNUSED(transform);
- return false;
+ Q_UNUSED(transform)
+ if (!m_view) {
+ 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::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);
if (!m_model || !m_view) {
return false;
}
- // Search the previously hovered item that might get unhovered
- KItemListWidget* unhoveredWidget = 0;
- foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) {
- if (widget->isHovered()) {
- unhoveredWidget = widget;
- break;
+ KItemListWidget* oldHoveredWidget = hoveredWidget();
+ KItemListWidget* newHoveredWidget = widgetForPos(event->pos());
+ if (oldHoveredWidget != newHoveredWidget) {
+ if (oldHoveredWidget) {
+ oldHoveredWidget->setHovered(false);
+ emit itemUnhovered(oldHoveredWidget->index());
}
- }
- // Search the currently hovered item
- KItemListWidget* hoveredWidget = 0;
- foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) {
- 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());
+ if (newHoveredWidget) {
+ newHoveredWidget->setHovered(true);
+ emit itemHovered(newHoveredWidget->index());
}
}
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"
class KItemListKeyboardSearchManager;
class KItemListSelectionManager;
class KItemListView;
+class KItemListWidget;
class QGraphicsSceneHoverEvent;
class QGraphicsSceneDragDropEvent;
class QGraphicsSceneMouseEvent;
* Is emitted if the item with the index \p index gets hovered.
*/
void itemHovered(int index);
+
/**
* Is emitted if the item with the index \p index gets unhovered.
* It is assured that the signal itemHovered() for this 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 viewChanged(KItemListView* current, KItemListView* previous);
*/
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:
SelectionBehavior m_selectionBehavior;
KItemModelBase* m_model;
return -1;
}
+bool KItemModelBase::supportsDropping(int index) const
+{
+ Q_UNUSED(index);
+ return false;
+}
+
void KItemModelBase::onGroupRoleChanged(const QByteArray& current, const QByteArray& previous)
{
Q_UNUSED(current);
* @param startFromIndex the index from which to start searching from
*/
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:
/**
* Is emitted if one or more items have been inserted. Each item-range consists
#include <QAbstractItemView>
#include <QApplication>
+#include <QBoxLayout>
#include <QClipboard>
+#include <QDropEvent>
+#include <QGraphicsSceneDragDropEvent>
#include <QKeyEvent>
#include <QItemSelection>
-#include <QBoxLayout>
#include <QTimer>
#include <QScrollBar>
#include "dolphin_detailsmodesettings.h"
#include "dolphin_generalsettings.h"
#include "dolphinitemlistcontainer.h"
+#include "draganddrophelper.h"
#include "renamedialog.h"
#include "settings/dolphinsettings.h"
#include "viewmodecontroller.h"
connect(controller, SIGNAL(itemExpansionToggleClicked(int)), this, SLOT(slotItemExpansionToggleClicked(int)));
connect(controller, SIGNAL(itemHovered(int)), this, SLOT(slotItemHovered(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();
connect(selectionManager, SIGNAL(selectionChanged(QSet<int>,QSet<int>)),
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)
{
const int currentCount = current.count();
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***************************************************************************/
-
#ifndef DOLPHINVIEW_H
#define DOLPHINVIEW_H
class KUrl;
class ToolTipManager;
class ViewProperties;
+class QGraphicsSceneDragDropEvent;
class QRegExp;
/**
void slotItemExpansionToggleClicked(int index);
void slotItemHovered(int index);
void slotItemUnhovered(int index);
+ void slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* event);
/**
* Emits the signal \a selectionChanged() with a small delay. This is
/***************************************************************************
- * 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> *
* *
* This program is free software; you can redistribute it and/or modify *
#include "draganddrophelper.h"
-#include <KDirModel>
#include <KFileItem>
-#include <KIcon>
#include <KLocale>
#include <konq_operations.h>
-
-#include "views/dolphiniconsview.h"
-#include "views/dolphinviewcontroller.h"
-
-#include <QAbstractItemView>
-#include <QAbstractProxyModel>
+#include <KUrl>
#include <QtDBus>
-#include <QDrag>
-#include <QPainter>
-
-class DragAndDropHelperSingleton
-{
-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);
-}
+#include <QDropEvent>
+#include <QWidget>
-void DragAndDropHelper::dropUrls(const KFileItem& destItem,
- const KUrl& destPath,
- QDropEvent* event,
- QWidget* widget)
+QString DragAndDropHelper::dropUrls(const KFileItem& destItem,
+ const KUrl& destPath,
+ QDropEvent* event,
+ QWidget* widget)
{
const bool dropToItem = !destItem.isNull() && (destItem.isDir() || destItem.isDesktopFile());
const KUrl destination = dropToItem ? destItem.url() : destPath;
const QMimeData* mimeData = event->mimeData();
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",
"org.kde.DndExtract", "extractSelectedFilesTo");
message.setArguments(QVariantList() << destination.pathOrUrl());
} else {
const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData());
const int urlsCount = urls.count();
- if ((urlsCount == 1) && (urls.first() == destination)) {
- emit errorMessage(i18nc("@info:status", "A folder cannot be dropped into itself"));
+ if (urlsCount == 1 && urls.first() == destination) {
+ return i18nc("@info:status", "A folder cannot be dropped into itself");
} else if (dropToItem) {
KonqOperations::doDrop(destItem, destination, event, widget);
} else {
KonqOperations::doDrop(KFileItem(), destination, event, widget);
}
}
-}
-
-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;
+ return QString();
}
-#include "draganddrophelper.moc"
/***************************************************************************
- * 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> *
* *
* This program is free software; you can redistribute it and/or modify *
#define DRAGANDDROPHELPER_H
#include "libdolphin_export.h"
-#include <QObject>
-#include <QPixmap>
-class DolphinViewController;
+#include <QString>
+
class KFileItem;
class KUrl;
class QDropEvent;
-class QAbstractItemView;
-class QMimeData;
class QWidget;
-/**
- * @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
+class LIBDOLPHINPRIVATE_EXPORT DragAndDropHelper
{
- Q_OBJECT
-
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
* destination. A context menu with the options
* @param destPath Path of the destination.
* @param event Drop event.
* @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,
- const KUrl& destPath,
- QDropEvent* event,
- 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;
+ static QString dropUrls(const KFileItem& destItem,
+ const KUrl& destPath,
+ QDropEvent* event,
+ QWidget* widget);
};
#endif