diff options
-rw-r--r-- | src/libs/cplusplus/OverviewModel.cpp | 33 | ||||
-rw-r--r-- | src/libs/cplusplus/OverviewModel.h | 5 | ||||
-rw-r--r-- | src/libs/utils/fileutils.cpp | 44 | ||||
-rw-r--r-- | src/libs/utils/fileutils.h | 8 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppoutline.cpp | 7 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppoutline.h | 1 | ||||
-rw-r--r-- | src/plugins/qmljseditor/qmljsoutline.cpp | 5 | ||||
-rw-r--r-- | src/plugins/qmljseditor/qmljsoutline.h | 1 | ||||
-rw-r--r-- | src/plugins/qmljseditor/qmloutlinemodel.cpp | 29 |
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; |