Skip to content

Commit

Permalink
Overview: abort play pos dragging if cursor is relased outside the va…
Browse files Browse the repository at this point in the history
…lid area

if the cursor leaves the valid area
* show a warning cursor
* remove the time ruler, restore regular play pos painting
  • Loading branch information
ronso0 committed Oct 9, 2024
1 parent 60bdaca commit d19c8be
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 1 deletion.
5 changes: 5 additions & 0 deletions res/images/cross_circle_red.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions res/mixxx.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
<RCC version="1.0">
<qresource prefix="/">
<file>../LICENSE</file>
<!-- for track dnd cursor -->
<file>images/library/ic_library_drag_and_drop.svg</file>
<!-- for drag abort cursor in overveiw waveform -->
<file>images/cross_circle_red.svg</file>
<!-- open/closed lock icons for BPM button -->
<file>images/library/ic_library_locked.svg</file>
<file>images/library/ic_library_unlocked.svg</file>
Expand Down
62 changes: 62 additions & 0 deletions src/widget/woverview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
#include "widget/controlwidgetconnection.h"
#include "wskincolor.h"

namespace {
// Horizontal and vertical margin around the widget where we accept play pos dragging.
constexpr int kDragOutsideLimitX = 100;
constexpr int kDragOutsideLimitY = 50;
} // anonymous namespace

WOverview::WOverview(
const QString& group,
PlayerManager* pPlayerManager,
Expand All @@ -50,6 +56,8 @@ WOverview::WOverview(
m_iPlayPos(0),
m_bTimeRulerActive(false),
m_orientation(Qt::Horizontal),
m_dragMarginH(kDragOutsideLimitX),
m_dragMarginV(kDragOutsideLimitY),
m_iLabelFontSize(10),
m_a(1.0),
m_b(0.0),
Expand Down Expand Up @@ -115,6 +123,12 @@ WOverview::WOverview(
this, &WOverview::onTrackAnalyzerProgress);

connect(m_pCueMenuPopup.get(), &WCueMenuPopup::aboutToHide, this, &WOverview::slotCueMenuPopupAboutToHide);

// Style the cursor we show when the cursor leaves the valid
// play pos dragging area.
QPixmap abortPixmap(32, 32);
abortPixmap.load(":/images/cross_circle_red.svg");
m_dragAbortCursor = QCursor(abortPixmap);
}

void WOverview::setup(const QDomNode& node, const SkinContext& context) {
Expand Down Expand Up @@ -226,6 +240,8 @@ void WOverview::setup(const QDomNode& node, const SkinContext& context) {
QString orientationString = context.selectString(node, "Orientation").toLower();
if (orientationString == "vertical") {
m_orientation = Qt::Vertical;
m_dragMarginH = kDragOutsideLimitY;
m_dragMarginV = kDragOutsideLimitX;
} else {
m_orientation = Qt::Horizontal;
}
Expand Down Expand Up @@ -487,6 +503,31 @@ void WOverview::receiveCuesUpdated() {

void WOverview::mouseMoveEvent(QMouseEvent* e) {
if (m_bLeftClickDragging) {
// Check if we're inside the valid dragging area
int x = 0, y = 0;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
x = static_cast<int>(e->position().x());
y = static_cast<int>(e->position().y());
#else
x = static_cast<int>(e->x());
y = static_cast<int>(e->y());
#endif
if (!isPosWithinPositionDragZone(x, y)) {
// Remove the time ruler to indicate dragging position is invalid
m_iPickupPos = m_iPlayPos;
m_bTimeRulerActive = false;

setCursor(m_dragAbortCursor);
// Remember to restore cursor everywhere where we cancel dragging
// Update immediately
update();
return;
} else {
m_bTimeRulerActive = true;
m_timeRulerPos = e->pos();
unsetCursor();
}

if (m_orientation == Qt::Horizontal) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
m_iPickupPos = math_clamp(static_cast<int>(e->position().x()), 0, width() - 1);
Expand Down Expand Up @@ -523,12 +564,32 @@ void WOverview::mouseReleaseEvent(QMouseEvent* e) {
mouseMoveEvent(e);
if (m_bPassthroughEnabled) {
m_bLeftClickDragging = false;
// We may be dragging, and we may be outside the valid dragging area
// (we'd show show the 'invalid drag' cursor then), so restore the cursor.
unsetCursor();
return;
}
//qDebug() << "WOverview::mouseReleaseEvent" << e->pos() << m_iPos << ">>" << dValue;

if (e->button() == Qt::LeftButton) {
if (m_bLeftClickDragging) {
unsetCursor();
// Abort dragging if we are way outside the widget.
int x = 0, y = 0;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
x = static_cast<int>(e->position().x());
y = static_cast<int>(e->position().y());
#else
x = static_cast<int>(e->x());
y = static_cast<int>(e->y());
#endif
if (!isPosWithinPositionDragZone(x, y)) {
m_iPickupPos = m_iPlayPos;
m_bLeftClickDragging = false;
m_bTimeRulerActive = false;
return;
}

m_iPlayPos = m_iPickupPos;
double dValue = positionToValue(m_iPickupPos);
setControlParameterUp(dValue);
Expand Down Expand Up @@ -584,6 +645,7 @@ void WOverview::mousePressEvent(QMouseEvent* e) {
m_iPickupPos = m_iPlayPos;
m_bLeftClickDragging = false;
m_bTimeRulerActive = false;
unsetCursor();
} else if (m_pHoveredMark == nullptr) {
m_bTimeRulerActive = true;
m_timeRulerPos = e->pos();
Expand Down
13 changes: 12 additions & 1 deletion src/widget/woverview.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,15 @@ class WOverview : public WWidget, public TrackDropTarget {
return m_orientation == Qt::Horizontal ? height() : width();
}

inline bool isPosWithinPositionDragZone(int x, int y) {
const QRect dragZone = rect().marginsAdded(QMargins(
m_dragMarginH,
m_dragMarginV,
m_dragMarginH,
m_dragMarginV));
return dragZone.contains(x, y);
}

ConstWaveformPointer getWaveform() const {
return m_pWaveform;
}
Expand Down Expand Up @@ -164,6 +173,8 @@ class WOverview : public WWidget, public TrackDropTarget {
int m_iPlayPos;
bool m_bTimeRulerActive;
Qt::Orientation m_orientation;
int m_dragMarginH;
int m_dragMarginV;
int m_iLabelFontSize;

// Coefficient value-position linear transposition
Expand Down Expand Up @@ -211,10 +222,10 @@ class WOverview : public WWidget, public TrackDropTarget {
QColor m_lowColor;
int m_dimBrightThreshold;
parented_ptr<QLabel> m_pPassthroughLabel;
QCursor m_dragAbortCursor;

WaveformMarkSet m_marks;
std::vector<WaveformMarkRange> m_markRanges;
WaveformMarkLabel m_cuePositionLabel;
WaveformMarkLabel m_cueTimeDistanceLabel;

};

0 comments on commit d19c8be

Please sign in to comment.