Commit fd9b2af9 authored by Eike Ziller's avatar Eike Ziller

Editors: Support drag & drop from bookmarks pane

Change-Id: I9b68d35b04968779f111885ba7a24f18fecfada5
Reviewed-by: default avatarDaniel Teske <daniel.teske@digia.com>
parent 72c33cba
......@@ -40,7 +40,6 @@
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QMessageBox>
#include <QMimeData>
#include <QTimer>
#include <QUrl>
......@@ -705,8 +704,16 @@ FileName &FileName::appendString(QChar str)
return *this;
}
static bool isDesktopFileManagerDrop(const QMimeData *d, QStringList *files = 0)
static bool isFileDrop(const QMimeData *d, QList<FileDropSupport::FileSpec> *files = 0)
{
// internal drop
if (const FileDropMimeData *internalData = qobject_cast<const FileDropMimeData *>(d)) {
if (files)
*files = internalData->files();
return true;
}
// external drop
if (files)
files->clear();
// Extract dropped files from Mime data.
......@@ -723,7 +730,7 @@ static bool isDesktopFileManagerDrop(const QMimeData *d, QStringList *files = 0)
if (!fileName.isEmpty()) {
hasFiles = true;
if (files)
files->push_back(fileName);
files->append(FileDropSupport::FileSpec(fileName));
else
break; // No result list, sufficient for checking
}
......@@ -745,27 +752,12 @@ QStringList FileDropSupport::mimeTypesForFilePaths()
return QStringList() << QStringLiteral("text/uri-list");
}
QMimeData *FileDropSupport::mimeDataForFilePaths(const QStringList &filePaths)
{
QList<QUrl> localUrls = Utils::transform(filePaths, [filePaths](const QString &path) {
return QUrl::fromLocalFile(path);
});
auto data = new QMimeData;
data->setUrls(localUrls);
return data;
}
QMimeData *FileDropSupport::mimeDataForFilePath(const QString &filePath)
{
return mimeDataForFilePaths(QStringList() << filePath);
}
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 (isFileDrop(dee->mimeData())
&& (!m_filterFunction || m_filterFunction(dee)))
event->accept();
else
......@@ -776,8 +768,8 @@ bool FileDropSupport::eventFilter(QObject *obj, QEvent *event)
return true;
} else if (event->type() == QEvent::Drop) {
auto de = static_cast<QDropEvent *>(event);
QStringList tempFiles;
if (isDesktopFileManagerDrop(de->mimeData(), &tempFiles)
QList<FileSpec> tempFiles;
if (isFileDrop(de->mimeData(), &tempFiles)
&& (!m_filterFunction || m_filterFunction(de))) {
event->accept();
de->acceptProposedAction();
......@@ -800,6 +792,21 @@ void FileDropSupport::emitFilesDropped()
m_files.clear();
}
void FileDropMimeData::addFile(const QString &filePath, int line, int column)
{
// standard mime data
QList<QUrl> currentUrls = urls();
currentUrls.append(QUrl::fromLocalFile(filePath));
setUrls(currentUrls);
// special mime data
m_files.append(FileDropSupport::FileSpec(filePath, line, column));
}
QList<FileDropSupport::FileSpec> FileDropMimeData::files() const
{
return m_files;
}
} // namespace Utils
QT_BEGIN_NAMESPACE
......
......@@ -35,6 +35,7 @@
#include <QCoreApplication>
#include <QXmlStreamWriter> // Mac.
#include <QMetaType>
#include <QMimeData>
#include <QStringList>
#include <functional>
......@@ -48,7 +49,6 @@ class QDir;
class QDropEvent;
class QFile;
class QFileInfo;
class QMimeData;
class QTemporaryFile;
class QTextStream;
class QWidget;
......@@ -202,6 +202,12 @@ class QTCREATOR_UTILS_EXPORT FileDropSupport : public QObject
{
Q_OBJECT
public:
struct FileSpec {
FileSpec(const QString &path, int r = -1, int c = -1) : filePath(path), line(r), column(c) {}
QString filePath;
int line;
int column;
};
// returns true if the event should be accepted
typedef std::function<bool(QDropEvent*)> DropFilterFunction;
......@@ -209,11 +215,9 @@ public:
= DropFilterFunction());
static QStringList mimeTypesForFilePaths();
static QMimeData *mimeDataForFilePaths(const QStringList &filePaths);
static QMimeData *mimeDataForFilePath(const QString &filePath);
signals:
void filesDropped(const QStringList &files);
void filesDropped(const QList<Utils::FileDropSupport::FileSpec> &files);
protected:
bool eventFilter(QObject *obj, QEvent *event);
......@@ -223,10 +227,21 @@ private slots:
private:
DropFilterFunction m_filterFunction;
QStringList m_files;
QList<FileSpec> m_files;
};
class QTCREATOR_UTILS_EXPORT FileDropMimeData : public QMimeData
{
Q_OBJECT
public:
void addFile(const QString &filePath, int line = -1, int column = -1);
QList<FileDropSupport::FileSpec> files() const;
private:
QList<FileDropSupport::FileSpec> m_files;
};
} // namespace Utils
QT_BEGIN_NAMESPACE
......
......@@ -229,6 +229,8 @@ BookmarkView::BookmarkView(BookmarkManager *manager) :
setSelectionModel(manager->selectionModel());
setSelectionMode(QAbstractItemView::SingleSelection);
setSelectionBehavior(QAbstractItemView::SelectRows);
setDragEnabled(true);
setDragDropMode(QAbstractItemView::DragOnly);
connect(this, SIGNAL(clicked(QModelIndex)),
this, SLOT(gotoBookmark(QModelIndex)));
......@@ -408,6 +410,35 @@ QVariant BookmarkManager::data(const QModelIndex &index, int role) const
return QVariant();
}
Qt::ItemFlags BookmarkManager::flags(const QModelIndex &index) const
{
if (!index.isValid() || index.column() !=0 || index.row() < 0 || index.row() >= m_bookmarksList.count())
return Qt::NoItemFlags;
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
}
Qt::DropActions BookmarkManager::supportedDragActions() const
{
return Qt::MoveAction;
}
QStringList BookmarkManager::mimeTypes() const
{
return FileDropSupport::mimeTypesForFilePaths();
}
QMimeData *BookmarkManager::mimeData(const QModelIndexList &indexes) const
{
auto data = new Utils::FileDropMimeData;
foreach (const QModelIndex &index, indexes) {
if (!index.isValid() || index.column() != 0 || index.row() < 0 || index.row() >= m_bookmarksList.count())
continue;
Bookmark *bookMark = m_bookmarksList.at(index.row());
data->addFile(bookMark->fileName(), bookMark->lineNumber());
}
return data;
}
void BookmarkManager::toggleBookmark()
{
BaseTextEditor *editor = BaseTextEditor::currentTextEditor();
......
......@@ -74,6 +74,11 @@ public:
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
Qt::DropActions supportedDragActions() const;
QStringList mimeTypes() const;
QMimeData *mimeData(const QModelIndexList &indexes) const;
// this QItemSelectionModel is shared by all views
QItemSelectionModel *selectionModel() const;
......
......@@ -426,14 +426,14 @@ Qt::ItemFlags DocumentModelPrivate::flags(const QModelIndex &index) const
QMimeData *DocumentModelPrivate::mimeData(const QModelIndexList &indexes) const
{
QStringList filePaths;
auto data = new Utils::FileDropMimeData;
foreach (const QModelIndex &index, indexes) {
const DocumentModel::Entry *e = DocumentModel::entryAtRow(index.row());
if (!e || e->fileName().isEmpty())
continue;
filePaths.append(e->fileName());
data->addFile(e->fileName());
}
return Utils::FileDropSupport::mimeDataForFilePaths(filePaths);
return data;
}
int DocumentModel::rowOfDocument(IDocument *document)
......
......@@ -577,6 +577,19 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const QString &fileN
return result;
}
IEditor *EditorManagerPrivate::openEditorAt(EditorView *view, const QString &fileName, int line,
int column, Id editorId,
EditorManager::OpenEditorFlags flags, bool *newEditor)
{
EditorManager::cutForwardNavigationHistory();
EditorManager::addCurrentPositionToNavigationHistory();
EditorManager::OpenEditorFlags tempFlags = flags | EditorManager::IgnoreNavigationHistory;
Core::IEditor *editor = openEditor(view, fileName, editorId, tempFlags, newEditor);
if (editor && line != -1)
editor->gotoLine(line, column);
return editor;
}
IEditor *EditorManagerPrivate::activateEditorForDocument(EditorView *view, IDocument *document,
EditorManager::OpenEditorFlags flags)
{
......@@ -2222,14 +2235,8 @@ IEditor *EditorManager::openEditor(const QString &fileName, Id editorId,
IEditor *EditorManager::openEditorAt(const QString &fileName, int line, int column,
Id editorId, OpenEditorFlags flags, bool *newEditor)
{
m_instance->cutForwardNavigationHistory();
m_instance->addCurrentPositionToNavigationHistory();
OpenEditorFlags tempFlags = flags | IgnoreNavigationHistory;
Core::IEditor *editor = Core::EditorManager::openEditor(fileName, editorId,
tempFlags, newEditor);
if (editor && line != -1)
editor->gotoLine(line, column);
return editor;
return EditorManagerPrivate::openEditorAt(EditorManagerPrivate::currentEditorView(),
fileName, line, column, editorId, flags, newEditor);
}
// Extract line number suffix. Return the suffix (e.g. ":132") and truncates the filename accordingly.
......
......@@ -75,6 +75,13 @@ public:
Id editorId = Id(),
EditorManager::OpenEditorFlags flags = EditorManager::NoFlags,
bool *newEditor = 0);
static IEditor *openEditorAt(EditorView *view,
const QString &fileName,
int line,
int column = 0,
Id editorId = Id(),
EditorManager::OpenEditorFlags flags = EditorManager::NoFlags,
bool *newEditor = 0);
static IEditor *duplicateEditor(IEditor *editor);
static IEditor *activateEditor(EditorView *view, IEditor *editor,
EditorManager::OpenEditorFlags flags = EditorManager::NoFlags);
......
......@@ -40,7 +40,6 @@
#include <coreplugin/minisplitter.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/findplaceholder.h>
#include <utils/fileutils.h>
#include <utils/qtcassert.h>
#include <QDebug>
......@@ -125,8 +124,8 @@ EditorView::EditorView(SplitterOrView *parentSplitterOrView, QWidget *parent) :
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)));
connect(dropSupport, &Utils::FileDropSupport::filesDropped,
this, &EditorView::openDroppedFiles);
updateNavigatorActions();
}
......@@ -350,11 +349,12 @@ void EditorView::closeSplit()
EditorManagerPrivate::updateActions();
}
void EditorView::openDroppedFiles(const QStringList &files)
void EditorView::openDroppedFiles(const QList<Utils::FileDropSupport::FileSpec> &files)
{
const int count = files.size();
for (int i = 0; i < count; ++i) {
EditorManagerPrivate::openEditor(this, files.at(i), Id(),
const Utils::FileDropSupport::FileSpec spec = files.at(i);
EditorManagerPrivate::openEditorAt(this, spec.filePath, spec.line, spec.column, Id(),
i < count - 1 ? EditorManager::DoNotChangeCurrentEditor
| EditorManager::DoNotMakeVisible
: EditorManager::NoFlags);
......
......@@ -32,6 +32,8 @@
#include "coreplugin/id.h"
#include <utils/fileutils.h>
#include <QMap>
#include <QList>
#include <QString>
......@@ -119,7 +121,7 @@ private slots:
void splitVertically();
void splitNewWindow();
void closeSplit();
void openDroppedFiles(const QStringList &files);
void openDroppedFiles(const QList<Utils::FileDropSupport::FileSpec> &files);
private:
friend class SplitterOrView; // for setParentSplitterOrView
......
......@@ -453,8 +453,10 @@ bool EditorToolBar::eventFilter(QObject *obj, QEvent *event)
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()));
auto drag = new QDrag(this);
auto data = new Utils::FileDropMimeData;
data->addFile(entry->fileName());
drag->setMimeData(data);
Qt::DropAction action = drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
if (action == Qt::MoveAction)
emit currentDocumentMoved();
......
......@@ -73,7 +73,7 @@
#include <coreplugin/progressmanager/progressmanager_p.h>
#include <coreplugin/progressmanager/progressview.h>
#include <coreplugin/settingsdatabase.h>
#include <utils/fileutils.h>
#include <utils/algorithm.h>
#include <utils/historycompleter.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
......@@ -212,8 +212,8 @@ MainWindow::MainWindow() :
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)));
connect(dropSupport, &Utils::FileDropSupport::filesDropped,
this, &MainWindow::openDroppedFiles);
}
void MainWindow::setSidebarVisible(bool visible)
......@@ -384,10 +384,14 @@ void MainWindow::closeEvent(QCloseEvent *event)
event->accept();
}
void MainWindow::openDroppedFiles(const QStringList &files)
void MainWindow::openDroppedFiles(const QList<Utils::FileDropSupport::FileSpec> &files)
{
raiseWindow();
openFiles(files, ICore::SwitchMode);
QStringList filePaths = Utils::transform(files,
[](const Utils::FileDropSupport::FileSpec &spec) -> QString {
return spec.filePath;
});
openFiles(filePaths, ICore::SwitchMode);
}
IContext *MainWindow::currentContextObject() const
......
......@@ -35,6 +35,7 @@
#include "dialogs/newdialog.h"
#include <utils/appmainwindow.h>
#include <utils/fileutils.h>
#include <QMap>
#include <QColor>
......@@ -148,7 +149,7 @@ private slots:
void updateFocusWidget(QWidget *old, QWidget *now);
void setSidebarVisible(bool visible);
void destroyVersionDialog();
void openDroppedFiles(const QStringList &files);
void openDroppedFiles(const QList<Utils::FileDropSupport::FileSpec> &files);
void restoreWindowState();
void newItemDialogFinished();
......
......@@ -500,13 +500,13 @@ QStringList FlatModel::mimeTypes() const
QMimeData *FlatModel::mimeData(const QModelIndexList &indexes) const
{
QStringList filePaths;
auto data = new Utils::FileDropMimeData;
foreach (const QModelIndex &index, indexes) {
Node *node = nodeForIndex(index);
if (qobject_cast<FileNode *>(node))
filePaths.append(node->path());
data->addFile(node->path());
}
return Utils::FileDropSupport::mimeDataForFilePaths(filePaths);
return data;
}
QModelIndex FlatModel::indexForNode(const Node *node_)
......
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