From 3d6b86ec3fb61c75682c3a5aecce45c6a6bc039a Mon Sep 17 00:00:00 2001 From: Alexey Andronov Date: Mon, 2 Dec 2019 23:59:10 +0700 Subject: [PATCH] ui: drag and drop selected source code from code view into other applications (#817) (issue #707) --- src/lib_gui/qt/element/code/QtCodeArea.cpp | 142 ++++++++++++++------- src/lib_gui/qt/element/code/QtCodeArea.h | 3 + 2 files changed, 100 insertions(+), 45 deletions(-) diff --git a/src/lib_gui/qt/element/code/QtCodeArea.cpp b/src/lib_gui/qt/element/code/QtCodeArea.cpp index 465e0c24..8df1a44d 100644 --- a/src/lib_gui/qt/element/code/QtCodeArea.cpp +++ b/src/lib_gui/qt/element/code/QtCodeArea.cpp @@ -3,14 +3,17 @@ #include #include +#include #include #include #include +#include #include #include #include #include #include +#include #include #include "ApplicationSettings.h" @@ -80,6 +83,7 @@ QtCodeArea::QtCodeArea( , m_digits(0) , m_isSelecting(false) , m_isPanning(false) + , m_isDragging(false) , m_setIDECursorPositionAction(nullptr) , m_eventPosition(0, 0) , m_isActiveFile(false) @@ -581,70 +585,89 @@ void QtCodeArea::mousePressEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) { - clearSelection(); - - m_oldMousePosition = event->pos(); - m_panningDistance = 0; - - if (Qt::KeyboardModifier::ShiftModifier & QApplication::keyboardModifiers()) + const QPoint clickPosition(event->pos()); + m_oldMousePosition = clickPosition; + if (isSelectionPosition(clickPosition)) { - m_isPanning = true; - viewport()->setCursor(Qt::ClosedHandCursor); + m_isDragging = true; } else { - m_isSelecting = true; - QTextCursor cursor = this->cursorForPosition(event->pos()); - setNewTextCursor(cursor); + clearSelection(); - viewport()->setCursor(Qt::IBeamCursor); + m_panningDistance = 0; + + if (Qt::KeyboardModifier::ShiftModifier & QApplication::keyboardModifiers()) + { + m_isPanning = true; + viewport()->setCursor(Qt::ClosedHandCursor); + } + else + { + m_isSelecting = true; + QTextCursor cursor = this->cursorForPosition(event->pos()); + setNewTextCursor(cursor); + + viewport()->setCursor(Qt::IBeamCursor); + } } } } void QtCodeArea::mouseReleaseEvent(QMouseEvent* event) { - const int panningThreshold = 5; - - if (event->button() == Qt::LeftButton) - { - m_isSelecting = false; - m_isPanning = false; - - viewport()->setCursor(Qt::ArrowCursor); - - if (m_panningDistance < panningThreshold) // dont do anything if mouse is release to end - // some real panning action. - { - if (Qt::KeyboardModifier::ControlModifier & QApplication::keyboardModifiers()) - { - m_eventPosition = event->pos(); - setIDECursorPosition(); - } - else - { - std::vector annotations = getInteractiveAnnotationsForPosition( - event->pos()); - if (annotations.size()) - { - activateAnnotationsOrErrors(annotations); - } - else if (m_navigator->getActiveLocalTokenIds().size()) - { - MessageActivateLocalSymbols(std::vector()).dispatch(); - } - } - } - } - else + if (event->button() != Qt::LeftButton) { QtCodeField::mouseReleaseEvent(event); + return; + } + + m_isSelecting = false; + m_isPanning = false; + + if (m_isDragging) + { + const int distance = (event->pos() - m_oldMousePosition).manhattanLength(); + if (distance < QApplication::startDragDistance()) + { + clearSelection(); + } + + m_isDragging = false; + return; + } + + viewport()->setCursor(Qt::ArrowCursor); + + const int panningThreshold = 5; + if (m_panningDistance < panningThreshold) // dont do anything if mouse is release to end + // some real panning action. + { + if (Qt::KeyboardModifier::ControlModifier & QApplication::keyboardModifiers()) + { + m_eventPosition = event->pos(); + setIDECursorPosition(); + } + else + { + std::vector annotations = getInteractiveAnnotationsForPosition( + event->pos()); + if (annotations.size()) + { + activateAnnotationsOrErrors(annotations); + } + else if (m_navigator->getActiveLocalTokenIds().size()) + { + MessageActivateLocalSymbols(std::vector()).dispatch(); + } + } } } void QtCodeArea::mouseMoveEvent(QMouseEvent* event) { const QPoint currentMousePosition = event->pos(); + const int delta = (currentMousePosition - m_oldMousePosition).manhattanLength(); const int deltaX = currentMousePosition.x() - m_oldMousePosition.x(); const int deltaY = currentMousePosition.y() - m_oldMousePosition.y(); m_oldMousePosition = currentMousePosition; @@ -663,6 +686,14 @@ void QtCodeArea::mouseMoveEvent(QMouseEvent* event) float deltaPosRatio = float(deltaX) / (visibleContentWidth); scrollbar->setValue(scrollbar->value() - std::round(deltaPosRatio * scrollbar->pageStep())); } + else if (m_isDragging) + { + if (delta >= QApplication::startDragDistance()) + { + dragSelectedText(); + m_isDragging = false; + } + } std::vector annotations = getInteractiveAnnotationsForPosition(event->pos()); @@ -805,6 +836,27 @@ void QtCodeArea::setNewTextCursor(const QTextCursor& cursor) verticalScrollBar()->setValue(verticalValue); } +void QtCodeArea::dragSelectedText() +{ + QMimeData* mimeData = new QMimeData; + const QString text = textCursor().selection().toPlainText(); + mimeData->setText(text); + + QDrag* drag = new QDrag(this); + drag->setMimeData(mimeData); + drag->exec(Qt::CopyAction); +} + +bool QtCodeArea::isSelectionPosition(const QPoint positionPoint) const +{ + const QTextCursor textCursor = QtCodeArea::textCursor(); + const int selectionStart = textCursor.selectionStart(); + const int selectionEnd = textCursor.selectionEnd(); + const QTextCursor positionCursor = this->cursorForPosition(positionPoint); + const int position = positionCursor.position(); + return selectionStart != selectionEnd && selectionStart <= position && position <= selectionEnd; +} + void QtCodeArea::activateAnnotationsOrErrors(const std::vector& annotations) { if (m_navigator->hasErrors()) diff --git a/src/lib_gui/qt/element/code/QtCodeArea.h b/src/lib_gui/qt/element/code/QtCodeArea.h index 49f1ed36..331043a7 100644 --- a/src/lib_gui/qt/element/code/QtCodeArea.h +++ b/src/lib_gui/qt/element/code/QtCodeArea.h @@ -107,6 +107,8 @@ private slots: private: void clearSelection(); void setNewTextCursor(const QTextCursor& cursor); + void dragSelectedText(); + bool isSelectionPosition(QPoint positionPoint) const; void activateAnnotationsOrErrors(const std::vector& annotations); @@ -121,6 +123,7 @@ private: bool m_isSelecting; bool m_isPanning; + bool m_isDragging; QPoint m_oldMousePosition; int m_panningDistance;