From 3d92f1f54d0e23051cf9428c25bfddeed494e629 Mon Sep 17 00:00:00 2001 From: itsmattkc <34096995+itsmattkc@users.noreply.github.com> Date: Wed, 24 Aug 2022 13:24:58 -0700 Subject: [PATCH] viewertexteditor: use hack to forward drag events --- app/widget/viewer/viewer.cpp | 3 - app/widget/viewer/viewerdisplay.cpp | 89 +++++++++++++++++++++++++++- app/widget/viewer/viewerdisplay.h | 3 + app/widget/viewer/viewertexteditor.h | 5 ++ 4 files changed, 94 insertions(+), 6 deletions(-) diff --git a/app/widget/viewer/viewer.cpp b/app/widget/viewer/viewer.cpp index a0a63f60f..fb8fde0da 100644 --- a/app/widget/viewer/viewer.cpp +++ b/app/widget/viewer/viewer.cpp @@ -86,7 +86,6 @@ ViewerWidget::ViewerWidget(QWidget *parent) : layout->addWidget(sizer_); display_widget_ = new ViewerDisplayWidget(); - display_widget_->setAcceptDrops(true); display_widget_->SetShowWidgetBackground(true); playback_devices_.append(display_widget_); connect(display_widget_, &ViewerDisplayWidget::customContextMenuRequested, this, &ViewerWidget::ShowContextMenu); @@ -148,8 +147,6 @@ ViewerWidget::ViewerWidget(QWidget *parent) : instances_.append(this); - setAcceptDrops(true); - UpdateWaveformViewFromMode(); connect(Core::instance(), &Core::ColorPickerEnabled, this, &ViewerWidget::SetSignalCursorColorEnabled); diff --git a/app/widget/viewer/viewerdisplay.cpp b/app/widget/viewer/viewerdisplay.cpp index 602352d80..3dc4edb8e 100644 --- a/app/widget/viewer/viewerdisplay.cpp +++ b/app/widget/viewer/viewerdisplay.cpp @@ -75,6 +75,8 @@ ViewerDisplayWidget::ViewerDisplayWidget(QWidget *parent) : const int kFrameRateAverageCount = 8; frame_rate_averages_.resize(kFrameRateAverageCount); + + inner_widget()->setAcceptDrops(true); } void ViewerDisplayWidget::SetMatrixTranslate(const QMatrix4x4 &mat) @@ -279,14 +281,59 @@ bool ViewerDisplayWidget::eventFilter(QObject *o, QEvent *e) } break; case QEvent::DragEnter: - emit DragEntered(static_cast(e)); + { + auto drag_enter = static_cast(e); + if (text_edit_) { + ForwardDragEventToTextEdit(drag_enter); + } else { + emit DragEntered(drag_enter); + } + + if (drag_enter->isAccepted()) { + return true; + } break; + } + case QEvent::DragMove: + { + auto drag_move = static_cast(e); + if (text_edit_) { + ForwardDragEventToTextEdit(drag_move); + } + + if (drag_move->isAccepted()) { + return true; + } + break; + } case QEvent::DragLeave: - emit DragLeft(static_cast(e)); + { + auto drag_leave = static_cast(e); + if (text_edit_) { + ForwardDragEventToTextEdit(drag_leave); + } else { + emit DragLeft(drag_leave); + } + + if (drag_leave->isAccepted()) { + return true; + } break; + } case QEvent::Drop: - emit Dropped(static_cast(e)); + { + auto drop = static_cast(e); + if (text_edit_) { + ForwardDragEventToTextEdit(drop); + } else { + emit Dropped(drop); + } + + if (drop->isAccepted()) { + return true; + } break; + } default: break; } @@ -1013,6 +1060,42 @@ void ViewerDisplayWidget::DrawSubtitleTracks() } } +template +void ViewerDisplayWidget::ForwardDragEventToTextEdit(T *e) +{ + // HACK: Absolutely filthy hack. We need to be able to transform the mouse coordinates for our + // proxied QTextEdit, however unlike QMouseEvents, Qt's drag events don't allow modifying + // the position after construction. Unhelpfully, Qt also explicitly forbids users creating + // their own drag events because they "rely on Qt's internal state". So in order to forward + // drag events, we defy this by creating our own events, but DON'T process them through Qt's + // event queue and instead just send them directly to the widget (requiring its protected + // drag events to be made public). That way Qt stays happy, because as far as it's + // concerned it's only interfacing with this widget, and the QTextEdit gets to receive + // transformed events. It's a terrible hack, but seems to work. + + if constexpr (std::is_same_v) { + text_edit_->dragLeaveEvent(e); + } else { + T relay(GetVirtualPosForTextEdit(e->posF()).toPoint(), + e->possibleActions(), + e->mimeData(), + e->mouseButtons(), + e->keyboardModifiers()); + + if (e->type() == QEvent::DragEnter) { + text_edit_->dragEnterEvent(static_cast(&relay)); + } else if (e->type() == QEvent::DragMove) { + text_edit_->dragMoveEvent(static_cast(&relay)); + } else if (e->type() == QEvent::Drop) { + text_edit_->dropEvent(&relay); + } + + if (relay.isAccepted()) { + e->accept(); + } + } +} + bool ViewerDisplayWidget::ForwardMouseEventToTextEdit(QMouseEvent *event, bool check_if_outside) { // Transform screen mouse coords to world mouse coords diff --git a/app/widget/viewer/viewerdisplay.h b/app/widget/viewer/viewerdisplay.h index bb189c4a2..24b6973df 100644 --- a/app/widget/viewer/viewerdisplay.h +++ b/app/widget/viewer/viewerdisplay.h @@ -269,6 +269,9 @@ private: void DrawSubtitleTracks(); + template + void ForwardDragEventToTextEdit(T *event); + bool ForwardMouseEventToTextEdit(QMouseEvent *event, bool check_if_outside = false); bool ForwardEventToTextEdit(QEvent *event); diff --git a/app/widget/viewer/viewertexteditor.h b/app/widget/viewer/viewertexteditor.h index 499f2e7d2..3f352b122 100644 --- a/app/widget/viewer/viewertexteditor.h +++ b/app/widget/viewer/viewertexteditor.h @@ -147,6 +147,11 @@ public: void Paint(QPainter *p, const QRect &clip = QRect()); + virtual void dragEnterEvent(QDragEnterEvent *e) override { return QTextEdit::dragEnterEvent(e); } + virtual void dragMoveEvent(QDragMoveEvent *e) override { return QTextEdit::dragMoveEvent(e); } + virtual void dragLeaveEvent(QDragLeaveEvent *e) override { return QTextEdit::dragLeaveEvent(e); } + virtual void dropEvent(QDropEvent *e) override { return QTextEdit::dropEvent(e); } + protected: virtual void paintEvent(QPaintEvent *event) override;