Commit e0c5d236 authored by Eike Ziller's avatar Eike Ziller
Browse files

Support drag and drop between splits



Change-Id: Ia1e43cb44639e332ee4f9100c7ce3029e9485198
Reviewed-by: default avatarAlessandro Portale <alessandro.portale@digia.com>
Reviewed-by: default avatarDaniel Teske <daniel.teske@digia.com>
parent 67421f6c
......@@ -711,8 +711,9 @@ static bool isDesktopFileManagerDrop(const QMimeData *d, QStringList *files = 0)
return hasFiles;
}
FileDropSupport::FileDropSupport(QWidget *parentWidget)
: QObject(parentWidget)
FileDropSupport::FileDropSupport(QWidget *parentWidget, const DropFilterFunction &filterFunction)
: QObject(parentWidget),
m_filterFunction(filterFunction)
{
QTC_ASSERT(parentWidget, return);
parentWidget->setAcceptDrops(true);
......@@ -744,15 +745,22 @@ bool FileDropSupport::eventFilter(QObject *obj, QEvent *event)
Q_UNUSED(obj)
if (event->type() == QEvent::DragEnter) {
auto dee = static_cast<QDragEnterEvent *>(event);
if (isDesktopFileManagerDrop(dee->mimeData()))
if (isDesktopFileManagerDrop(dee->mimeData())
&& (!m_filterFunction || m_filterFunction(dee)))
event->accept();
else
event->ignore();
return true;
} else if (event->type() == QEvent::DragMove) {
event->accept();
return true;
} else if (event->type() == QEvent::Drop) {
auto de = static_cast<QDropEvent *>(event);
QStringList tempFiles;
if (isDesktopFileManagerDrop(de->mimeData(), &tempFiles)) {
if (isDesktopFileManagerDrop(de->mimeData(), &tempFiles)
&& (!m_filterFunction || m_filterFunction(de))) {
event->accept();
de->acceptProposedAction();
bool needToScheduleEmit = m_files.isEmpty();
m_files.append(tempFiles);
if (needToScheduleEmit) // otherwise we already have a timer pending
......@@ -760,6 +768,7 @@ bool FileDropSupport::eventFilter(QObject *obj, QEvent *event)
} else {
event->ignore();
}
return true;
}
return false;
}
......
......@@ -37,18 +37,21 @@
#include <QMetaType>
#include <QStringList>
#include <functional>
namespace Utils {class FileName; }
QT_BEGIN_NAMESPACE
class QDataStream;
class QDateTime;
class QDir;
class QDropEvent;
class QFile;
class QFileInfo;
class QMimeData;
class QTemporaryFile;
class QWidget;
class QTextStream;
class QDataStream;
class QDateTime;
class QFileInfo;
class QDir;
class QWidget;
QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug dbg, const Utils::FileName &c);
......@@ -198,7 +201,11 @@ class QTCREATOR_UTILS_EXPORT FileDropSupport : public QObject
{
Q_OBJECT
public:
FileDropSupport(QWidget *parentWidget);
// returns true if the event should be accepted
typedef std::function<bool(QDropEvent*)> DropFilterFunction;
FileDropSupport(QWidget *parentWidget, const DropFilterFunction &filterFunction
= DropFilterFunction());
static QStringList mimeTypesForFilePaths();
static QMimeData *mimeDataForFilePaths(const QStringList &filePaths);
......@@ -214,6 +221,7 @@ private slots:
void emitFilesDropped();
private:
DropFilterFunction m_filterFunction;
QStringList m_files;
};
......
......@@ -78,6 +78,7 @@ EditorView::EditorView(SplitterOrView *parentSplitterOrView, QWidget *parent) :
connect(m_toolBar, SIGNAL(goForwardClicked()), this, SLOT(goForwardInNavigationHistory()));
connect(m_toolBar, SIGNAL(closeClicked()), this, SLOT(closeCurrentEditor()));
connect(m_toolBar, SIGNAL(listSelectionActivated(int)), this, SLOT(listSelectionActivated(int)));
connect(m_toolBar, &EditorToolBar::currentDocumentMoved, this, &EditorView::closeCurrentEditor);
connect(m_toolBar, SIGNAL(horizontalSplitClicked()), this, SLOT(splitHorizontally()));
connect(m_toolBar, SIGNAL(verticalSplitClicked()), this, SLOT(splitVertically()));
connect(m_toolBar, SIGNAL(splitNewWindowClicked()), this, SLOT(splitNewWindow()));
......@@ -122,7 +123,9 @@ EditorView::EditorView(SplitterOrView *parentSplitterOrView, QWidget *parent) :
m_container->addWidget(empty);
m_widgetEditorMap.insert(empty, 0);
auto dropSupport = new Utils::FileDropSupport(this);
auto dropSupport = new Utils::FileDropSupport(this, [this](QDropEvent *event) {
return event->source() != m_toolBar; // do not accept drops on ourselves
});
connect(dropSupport, SIGNAL(filesDropped(QStringList)),
this, SLOT(openDroppedFiles(QStringList)));
......
......@@ -29,24 +29,32 @@
#include "editortoolbar.h"
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icore.h>
#include <coreplugin/editormanager/documentmodel.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/editormanager_p.h>
#include <coreplugin/editormanager/documentmodel.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <QDir>
#include <QApplication>
#include <QComboBox>
#include <QVBoxLayout>
#include <QToolButton>
#include <QDir>
#include <QDrag>
#include <QLabel>
#include <QMenu>
#include <QMimeData>
#include <QMouseEvent>
#include <QTimer>
#include <QToolButton>
#include <QVBoxLayout>
#include <QDebug>
enum {
debug = false
......@@ -61,6 +69,7 @@ struct EditorToolBarPrivate
QComboBox *m_editorList;
QToolButton *m_closeEditorButton;
QToolButton *m_lockButton;
QToolButton *m_dragHandle;
QAction *m_goBackAction;
QAction *m_goForwardAction;
QToolButton *m_backButton;
......@@ -75,22 +84,25 @@ struct EditorToolBarPrivate
QWidget *m_toolBarPlaceholder;
QWidget *m_defaultToolBar;
QPoint m_dragStartPosition;
bool m_isStandalone;
};
EditorToolBarPrivate::EditorToolBarPrivate(QWidget *parent, EditorToolBar *q) :
m_editorList(new QComboBox(q)),
m_closeEditorButton(new QToolButton),
m_lockButton(new QToolButton),
m_closeEditorButton(new QToolButton(q)),
m_lockButton(new QToolButton(q)),
m_dragHandle(new QToolButton(q)),
m_goBackAction(new QAction(QIcon(QLatin1String(Constants::ICON_PREV)), EditorManager::tr("Go Back"), parent)),
m_goForwardAction(new QAction(QIcon(QLatin1String(Constants::ICON_NEXT)), EditorManager::tr("Go Forward"), parent)),
m_splitButton(new QToolButton),
m_splitButton(new QToolButton(q)),
m_horizontalSplitAction(new QAction(QIcon(QLatin1String(Constants::ICON_SPLIT_HORIZONTAL)), EditorManager::tr("Split"), parent)),
m_verticalSplitAction(new QAction(QIcon(QLatin1String(Constants::ICON_SPLIT_VERTICAL)), EditorManager::tr("Split Side by Side"), parent)),
m_splitNewWindowAction(new QAction(EditorManager::tr("Open in New Window"), parent)),
m_closeSplitButton(new QToolButton),
m_closeSplitButton(new QToolButton(q)),
m_activeToolBar(0),
m_toolBarPlaceholder(new QWidget),
m_toolBarPlaceholder(new QWidget(q)),
m_defaultToolBar(new QWidget(q)),
m_isStandalone(false)
{
......@@ -115,6 +127,11 @@ EditorToolBar::EditorToolBar(QWidget *parent) :
d->m_lockButton->setAutoRaise(true);
d->m_lockButton->setEnabled(false);
d->m_dragHandle->setCheckable(false);
d->m_dragHandle->setChecked(false);
d->m_dragHandle->setToolTip(tr("Drag to drag documents between splits"));
d->m_dragHandle->installEventFilter(this);
connect(d->m_goBackAction, SIGNAL(triggered()), this, SIGNAL(goBackClicked()));
connect(d->m_goForwardAction, SIGNAL(triggered()), this, SIGNAL(goForwardClicked()));
......@@ -164,6 +181,7 @@ EditorToolBar::EditorToolBar(QWidget *parent) :
toplayout->addWidget(d->m_backButton);
toplayout->addWidget(d->m_forwardButton);
toplayout->addWidget(d->m_lockButton);
toplayout->addWidget(d->m_dragHandle);
toplayout->addWidget(d->m_editorList);
toplayout->addWidget(d->m_closeEditorButton);
toplayout->addWidget(d->m_toolBarPlaceholder, 1); // Custom toolbar stretches
......@@ -367,6 +385,7 @@ void EditorToolBar::updateDocumentStatus(IDocument *document)
d->m_lockButton->setIcon(QIcon());
d->m_lockButton->setEnabled(false);
d->m_lockButton->setToolTip(QString());
d->m_dragHandle->setIcon(QIcon());
d->m_editorList->setToolTip(QString());
return;
}
......@@ -386,12 +405,50 @@ void EditorToolBar::updateDocumentStatus(IDocument *document)
d->m_lockButton->setEnabled(false);
d->m_lockButton->setToolTip(tr("File is writable"));
}
if (document->filePath().isEmpty())
d->m_dragHandle->setIcon(QIcon());
else
d->m_dragHandle->setIcon(FileIconProvider::icon(QFileInfo(document->filePath())));
d->m_editorList->setToolTip(
document->filePath().isEmpty()
? document->displayName()
: QDir::toNativeSeparators(document->filePath()));
}
bool EditorToolBar::eventFilter(QObject *obj, QEvent *event)
{
if (obj == d->m_dragHandle) {
if (event->type() == QEvent::MouseButtonPress) {
auto me = static_cast<QMouseEvent *>(event);
if (me->buttons() == Qt::LeftButton) {
d->m_dragStartPosition = me->pos();
return true;
}
return Utils::StyledBar::eventFilter(obj, event);
} else if (event->type() == QEvent::MouseMove) {
auto me = static_cast<QMouseEvent *>(event);
if (me->buttons() != Qt::LeftButton)
return Utils::StyledBar::eventFilter(obj, event);
if ((me->pos() - d->m_dragStartPosition).manhattanLength()
< QApplication::startDragDistance())
return Utils::StyledBar::eventFilter(obj, event);
DocumentModel::Entry *entry = DocumentModel::entryAtRow(
d->m_editorList->currentIndex());
if (!entry) // no document
return Utils::StyledBar::eventFilter(obj, event);
auto *drag = new QDrag(this);
drag->setMimeData(Utils::FileDropSupport::mimeDataForFilePath(entry->fileName()));
Qt::DropAction action = drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
if (action == Qt::MoveAction)
emit currentDocumentMoved();
return true;
}
}
return Utils::StyledBar::eventFilter(obj, event);
}
void EditorToolBar::setNavigationVisible(bool isVisible)
{
d->m_goBackAction->setVisible(isVisible);
......
......@@ -94,11 +94,15 @@ signals:
void closeSplitClicked();
void listSelectionActivated(int row);
void listContextMenuRequested(QPoint globalpos);
void currentDocumentMoved();
protected:
bool eventFilter(QObject *obj, QEvent *event);
private slots:
void updateEditorListSelection(Core::IEditor *newSelection);
void changeActiveEditor(int row);
void listContextMenu(QPoint);
void listContextMenu(QPoint pos);
void makeEditorWritable();
void checkDocumentStatus();
......
......@@ -207,7 +207,9 @@ MainWindow::MainWindow() :
statusBar()->setProperty("p_styled", true);
auto dropSupport = new Utils::FileDropSupport(this);
auto dropSupport = new Utils::FileDropSupport(this, [](QDropEvent *event) {
return event->source() == 0; // only accept drops from the "outside" (e.g. file manager)
});
connect(dropSupport, SIGNAL(filesDropped(QStringList)),
this, SLOT(openDroppedFiles(QStringList)));
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment