summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libs/cplusplus/OverviewModel.cpp33
-rw-r--r--src/libs/cplusplus/OverviewModel.h5
-rw-r--r--src/libs/utils/fileutils.cpp44
-rw-r--r--src/libs/utils/fileutils.h8
-rw-r--r--src/plugins/cppeditor/cppoutline.cpp7
-rw-r--r--src/plugins/cppeditor/cppoutline.h1
-rw-r--r--src/plugins/qmljseditor/qmljsoutline.cpp5
-rw-r--r--src/plugins/qmljseditor/qmljsoutline.h1
-rw-r--r--src/plugins/qmljseditor/qmloutlinemodel.cpp29
9 files changed, 119 insertions, 14 deletions
diff --git a/src/libs/cplusplus/OverviewModel.cpp b/src/libs/cplusplus/OverviewModel.cpp
index 372d80fe5a..e016109017 100644
--- a/src/libs/cplusplus/OverviewModel.cpp
+++ b/src/libs/cplusplus/OverviewModel.cpp
@@ -34,6 +34,7 @@
#include <cplusplus/Scope.h>
#include <cplusplus/Literals.h>
#include <cplusplus/Symbols.h>
+#include <utils/fileutils.h>
using namespace CPlusPlus;
@@ -242,3 +243,35 @@ void OverviewModel::rebuild(Document::Ptr doc)
_cppDocument = doc;
endResetModel();
}
+
+Qt::ItemFlags OverviewModel::flags(const QModelIndex &index) const
+{
+ Q_UNUSED(index)
+ return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
+}
+
+Qt::DropActions OverviewModel::supportedDragActions() const
+{
+ return Qt::MoveAction;
+}
+
+QStringList OverviewModel::mimeTypes() const
+{
+ return Utils::FileDropSupport::mimeTypesForFilePaths();
+}
+
+QMimeData *OverviewModel::mimeData(const QModelIndexList &indexes) const
+{
+ auto mimeData = new Utils::FileDropMimeData;
+ foreach (const QModelIndex &index, indexes) {
+ const QVariant fileName = data(index, FileNameRole);
+ if (!fileName.canConvert<QString>())
+ continue;
+ const QVariant lineNumber = data(index, LineNumberRole);
+ if (!fileName.canConvert<unsigned>())
+ continue;
+ mimeData->addFile(fileName.toString(), lineNumber.value<unsigned>());
+ }
+ return mimeData;
+}
+
diff --git a/src/libs/cplusplus/OverviewModel.h b/src/libs/cplusplus/OverviewModel.h
index 3f739c2a66..683da81c62 100644
--- a/src/libs/cplusplus/OverviewModel.h
+++ b/src/libs/cplusplus/OverviewModel.h
@@ -61,6 +61,11 @@ public:
Document::Ptr document() const;
Symbol *symbolFromIndex(const QModelIndex &index) const;
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+ Qt::DropActions supportedDragActions() const;
+ QStringList mimeTypes() const;
+ QMimeData *mimeData(const QModelIndexList &indexes) const;
+
public Q_SLOTS:
void rebuild(CPlusPlus::Document::Ptr doc);
diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp
index a314c69ff5..1a07192066 100644
--- a/src/libs/utils/fileutils.cpp
+++ b/src/libs/utils/fileutils.cpp
@@ -778,12 +778,22 @@ bool FileDropSupport::eventFilter(QObject *obj, QEvent *event)
QList<FileSpec> tempFiles;
if (isFileDrop(de->mimeData(), &tempFiles)
&& (!m_filterFunction || m_filterFunction(de))) {
+ const FileDropMimeData *fileDropMimeData = qobject_cast<const FileDropMimeData *>(de->mimeData());
event->accept();
- de->acceptProposedAction();
+ if (fileDropMimeData && fileDropMimeData->isOverridingFileDropAction())
+ de->setDropAction(fileDropMimeData->overrideFileDropAction());
+ else
+ de->acceptProposedAction();
bool needToScheduleEmit = m_files.isEmpty();
m_files.append(tempFiles);
- if (needToScheduleEmit) // otherwise we already have a timer pending
- QTimer::singleShot(0, this, SLOT(emitFilesDropped()));
+ if (needToScheduleEmit) { // otherwise we already have a timer pending
+ // Delay the actual drop, to avoid conflict between
+ // actions that happen when opening files, and actions that the item views do
+ // after the drag operation.
+ // If we do not do this, e.g. dragging from Outline view crashes if the editor and
+ // the selected item changes
+ QTimer::singleShot(100, this, SLOT(emitFilesDropped()));
+ }
} else {
event->ignore();
}
@@ -799,6 +809,34 @@ void FileDropSupport::emitFilesDropped()
m_files.clear();
}
+/*!
+ Sets the drop action to effectively use, instead of the "proposed" drop action from the
+ drop event. This can be useful when supporting move drags within an item view, but not
+ "moving" an item from the item view into a split.
+ */
+FileDropMimeData::FileDropMimeData()
+ : m_overrideDropAction(Qt::IgnoreAction),
+ m_isOverridingDropAction(false)
+{
+
+}
+
+void FileDropMimeData::setOverrideFileDropAction(Qt::DropAction action)
+{
+ m_isOverridingDropAction = true;
+ m_overrideDropAction = action;
+}
+
+Qt::DropAction FileDropMimeData::overrideFileDropAction() const
+{
+ return m_overrideDropAction;
+}
+
+bool FileDropMimeData::isOverridingFileDropAction() const
+{
+ return m_isOverridingDropAction;
+}
+
void FileDropMimeData::addFile(const QString &filePath, int line, int column)
{
// standard mime data
diff --git a/src/libs/utils/fileutils.h b/src/libs/utils/fileutils.h
index 1f20d645ff..df874c0d92 100644
--- a/src/libs/utils/fileutils.h
+++ b/src/libs/utils/fileutils.h
@@ -236,11 +236,19 @@ class QTCREATOR_UTILS_EXPORT FileDropMimeData : public QMimeData
{
Q_OBJECT
public:
+ FileDropMimeData();
+
+ void setOverrideFileDropAction(Qt::DropAction action);
+ Qt::DropAction overrideFileDropAction() const;
+ bool isOverridingFileDropAction() const;
+
void addFile(const QString &filePath, int line = -1, int column = -1);
QList<FileDropSupport::FileSpec> files() const;
private:
QList<FileDropSupport::FileSpec> m_files;
+ Qt::DropAction m_overrideDropAction;
+ bool m_isOverridingDropAction;
};
} // namespace Utils
diff --git a/src/plugins/cppeditor/cppoutline.cpp b/src/plugins/cppeditor/cppoutline.cpp
index 463ebf3983..635b42a92a 100644
--- a/src/plugins/cppeditor/cppoutline.cpp
+++ b/src/plugins/cppeditor/cppoutline.cpp
@@ -51,6 +51,8 @@ CppOutlineTreeView::CppOutlineTreeView(QWidget *parent) :
Utils::NavigationTreeView(parent)
{
setExpandsOnDoubleClick(false);
+ setDragEnabled(true);
+ setDragDropMode(QAbstractItemView::DragOnly);
}
void CppOutlineTreeView::contextMenuEvent(QContextMenuEvent *event)
@@ -90,6 +92,11 @@ bool CppOutlineFilterModel::filterAcceptsRow(int sourceRow,
return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
}
+Qt::DropActions CppOutlineFilterModel::supportedDragActions() const
+{
+ return sourceModel()->supportedDragActions();
+}
+
CppOutlineWidget::CppOutlineWidget(CppEditorWidget *editor) :
TextEditor::IOutlineWidget(),
diff --git a/src/plugins/cppeditor/cppoutline.h b/src/plugins/cppeditor/cppoutline.h
index 0092bd9b4f..f264439d2e 100644
--- a/src/plugins/cppeditor/cppoutline.h
+++ b/src/plugins/cppeditor/cppoutline.h
@@ -60,6 +60,7 @@ public:
// QSortFilterProxyModel
bool filterAcceptsRow(int sourceRow,
const QModelIndex &sourceParent) const;
+ Qt::DropActions supportedDragActions() const;
private:
CPlusPlus::OverviewModel *m_sourceModel;
};
diff --git a/src/plugins/qmljseditor/qmljsoutline.cpp b/src/plugins/qmljseditor/qmljsoutline.cpp
index d2996fc073..6d7ccdd3f0 100644
--- a/src/plugins/qmljseditor/qmljsoutline.cpp
+++ b/src/plugins/qmljseditor/qmljsoutline.cpp
@@ -82,6 +82,11 @@ QVariant QmlJSOutlineFilterModel::data(const QModelIndex &index, int role) const
return QSortFilterProxyModel::data(index, role);
}
+Qt::DropActions QmlJSOutlineFilterModel::supportedDragActions() const
+{
+ return sourceModel()->supportedDragActions();
+}
+
bool QmlJSOutlineFilterModel::filterBindings() const
{
return m_filterBindings;
diff --git a/src/plugins/qmljseditor/qmljsoutline.h b/src/plugins/qmljseditor/qmljsoutline.h
index f9be1d0716..0b984d4603 100644
--- a/src/plugins/qmljseditor/qmljsoutline.h
+++ b/src/plugins/qmljseditor/qmljsoutline.h
@@ -54,6 +54,7 @@ public:
bool filterAcceptsRow(int sourceRow,
const QModelIndex &sourceParent) const;
QVariant data(const QModelIndex &index, int role) const;
+ Qt::DropActions supportedDragActions() const;
bool filterBindings() const;
void setFilterBindings(bool filterBindings);
diff --git a/src/plugins/qmljseditor/qmloutlinemodel.cpp b/src/plugins/qmljseditor/qmloutlinemodel.cpp
index 88b425739d..9b5443552f 100644
--- a/src/plugins/qmljseditor/qmloutlinemodel.cpp
+++ b/src/plugins/qmljseditor/qmloutlinemodel.cpp
@@ -37,6 +37,7 @@
#include <qmljs/qmljsrewriter.h>
#include <qmljstools/qmljsrefactoringchanges.h>
+#include <utils/fileutils.h>
#include <utils/qtcassert.h>
#include <coreplugin/icore.h>
@@ -53,6 +54,8 @@ enum {
debug = false
};
+static const char INTERNAL_MIMETYPE[] = "application/x-qtcreator-qmloutlinemodel";
+
namespace QmlJSEditor {
namespace Internal {
@@ -312,7 +315,8 @@ QmlOutlineModel::QmlOutlineModel(QmlJSEditorDocument *document) :
QStringList QmlOutlineModel::mimeTypes() const
{
QStringList types;
- types << QLatin1String("application/x-qtcreator-qmloutlinemodel");
+ types << QLatin1String(INTERNAL_MIMETYPE);
+ types << Utils::FileDropSupport::mimeTypesForFilePaths();
return types;
}
@@ -321,9 +325,8 @@ QMimeData *QmlOutlineModel::mimeData(const QModelIndexList &indexes) const
{
if (indexes.count() <= 0)
return 0;
- QStringList types = mimeTypes();
- QMimeData *data = new QMimeData();
- QString format = types.at(0);
+ auto data = new Utils::FileDropMimeData;
+ data->setOverrideFileDropAction(Qt::CopyAction);
QByteArray encoded;
QDataStream stream(&encoded, QIODevice::WriteOnly);
stream << indexes.size();
@@ -331,6 +334,10 @@ QMimeData *QmlOutlineModel::mimeData(const QModelIndexList &indexes) const
for (int i = 0; i < indexes.size(); ++i) {
QModelIndex index = indexes.at(i);
+ AST::SourceLocation location = sourceLocation(index);
+ data->addFile(m_editorDocument->filePath(), location.startLine,
+ location.startColumn - 1 /*editors have 0-based column*/);
+
QList<int> rowPath;
for (QModelIndex i = index; i.isValid(); i = i.parent()) {
rowPath.prepend(i.row());
@@ -338,7 +345,7 @@ QMimeData *QmlOutlineModel::mimeData(const QModelIndexList &indexes) const
stream << rowPath;
}
- data->setData(format, encoded);
+ data->setData(QLatin1String(INTERNAL_MIMETYPE), encoded);
return data;
}
@@ -410,8 +417,8 @@ Qt::ItemFlags QmlOutlineModel::flags(const QModelIndex &index) const
Qt::DropActions QmlOutlineModel::supportedDragActions() const
{
- // TODO: Maybe add a Copy Action?
- return Qt::MoveAction;
+ // copy action used for dragging onto editor splits
+ return Qt::MoveAction | Qt::CopyAction;
}
@@ -915,7 +922,7 @@ QString QmlOutlineModel::asString(AST::UiQualifiedId *id)
AST::SourceLocation QmlOutlineModel::getLocation(AST::UiObjectMember *objMember) {
AST::SourceLocation location;
- location.offset = objMember->firstSourceLocation().offset;
+ location = objMember->firstSourceLocation();
location.length = objMember->lastSourceLocation().offset
- objMember->firstSourceLocation().offset
+ objMember->lastSourceLocation().length;
@@ -924,7 +931,7 @@ AST::SourceLocation QmlOutlineModel::getLocation(AST::UiObjectMember *objMember)
AST::SourceLocation QmlOutlineModel::getLocation(AST::ExpressionNode *exprNode) {
AST::SourceLocation location;
- location.offset = exprNode->firstSourceLocation().offset;
+ location = exprNode->firstSourceLocation();
location.length = exprNode->lastSourceLocation().offset
- exprNode->firstSourceLocation().offset
+ exprNode->lastSourceLocation().length;
@@ -941,7 +948,7 @@ AST::SourceLocation QmlOutlineModel::getLocation(AST::PropertyAssignmentList *pr
AST::SourceLocation QmlOutlineModel::getLocation(AST::PropertyNameAndValue *propertyNode) {
AST::SourceLocation location;
- location.offset = propertyNode->name->propertyNameToken.offset;
+ location = propertyNode->name->propertyNameToken;
location.length = propertyNode->value->lastSourceLocation().end() - location.offset;
return location;
@@ -949,7 +956,7 @@ AST::SourceLocation QmlOutlineModel::getLocation(AST::PropertyNameAndValue *prop
AST::SourceLocation QmlOutlineModel::getLocation(AST::PropertyGetterSetter *propertyNode) {
AST::SourceLocation location;
- location.offset = propertyNode->name->propertyNameToken.offset;
+ location = propertyNode->name->propertyNameToken;
location.length = propertyNode->rbraceToken.end() - location.offset;
return location;