From c54ee90436a74d7217d7d87a0f1fff161bc912be Mon Sep 17 00:00:00 2001
From: Elliu <elliu@hashi.re>
Date: Thu, 3 Feb 2022 03:14:57 +0100
Subject: [PATCH] Fix drag-and drop for start of line bar

---
 .../AudioVisualizer/TimingLine.cc             | 59 +++++++++++++++----
 .../AudioVisualizer/TimingLine.hh             |  6 +-
 .../AudioVisualizer/TimingSeparator.cc        | 37 ++++++++++--
 .../AudioVisualizer/TimingSeparator.hh        | 10 ++++
 4 files changed, 96 insertions(+), 16 deletions(-)

diff --git a/src/UI/DocumentViews/AudioVisualizer/TimingLine.cc b/src/UI/DocumentViews/AudioVisualizer/TimingLine.cc
index 26f920c1..a4562231 100644
--- a/src/UI/DocumentViews/AudioVisualizer/TimingLine.cc
+++ b/src/UI/DocumentViews/AudioVisualizer/TimingLine.cc
@@ -12,8 +12,6 @@ TimingLine::TimingLine(Ass::Line *lineptr, QGraphicsItem *parent)
     , line(*lineptr)
 {
     setPos(TimingUtils::posFromMs(int(line.getStart()) * 10), TimingUtils::axisHeight());
-    originalX       = pos().x();
-    originalY       = pos().y();
     int currentTime = 0;
     int endSyl      = 0;
     int i;
@@ -23,6 +21,8 @@ TimingLine::TimingLine(Ass::Line *lineptr, QGraphicsItem *parent)
     seps.append(timingSeparatorStart);
     connect(timingSeparatorStart, &TimingSeparator::positionChanged, this,
             &TimingLine::timingSeparatorHasChanged);
+    connect(timingSeparatorStart, &TimingSeparator::enterPress, this, &TimingLine::sepEnterPress);
+    connect(timingSeparatorStart, &TimingSeparator::exitPress, this, &TimingLine::sepExitPress);
 
     QVector<Ass::Syl> syls = line.getContent();
     for (i = 0; i < syls.size(); ++i) {
@@ -38,6 +38,9 @@ TimingLine::TimingLine(Ass::Line *lineptr, QGraphicsItem *parent)
             seps.append(timingSeparator);
             connect(timingSeparator, &TimingSeparator::positionChanged, this,
                     &TimingLine::timingSeparatorHasChanged);
+            connect(timingSeparator, &TimingSeparator::enterPress, this,
+                    &TimingLine::sepEnterPress);
+            connect(timingSeparator, &TimingSeparator::exitPress, this, &TimingLine::sepExitPress);
         }
 
         currentTime = endSyl;
@@ -48,22 +51,26 @@ TimingLine::TimingLine(Ass::Line *lineptr, QGraphicsItem *parent)
     seps.append(timingSeparatorEnd);
     connect(timingSeparatorEnd, &TimingSeparator::positionChanged, this,
             &TimingLine::timingSeparatorHasChanged);
+    connect(timingSeparatorEnd, &TimingSeparator::enterPress, this, &TimingLine::sepEnterPress);
+    connect(timingSeparatorEnd, &TimingSeparator::exitPress, this, &TimingLine::sepExitPress);
 }
 
 QRectF
 TimingLine::boundingRect() const
 {
-    return QRectF(0, 0, TimingUtils::posFromMs(int(10 * (line.getEnd() - line.getStart()))),
+    return QRectF(tempOffset, 0,
+                  TimingUtils::posFromMs(int(10 * (line.getEnd() - line.getStart()))),
                   TimingUtils::audioHeight());
 }
 
 void
 TimingLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
 {
-    painter->fillRect(QRectF(0, 0,
-                             TimingUtils::posFromMs(int(10 * (line.getEnd() - line.getStart()))),
-                             TimingUtils::audioHeight()),
-                      QColor(0, 255, 255, 50));
+    painter->fillRect(
+        QRectF(tempOffset, 0,
+               TimingUtils::posFromMs(int(10 * (line.getEnd() - line.getStart()))),
+               TimingUtils::audioHeight()),
+        QColor(0, 255, 255, 50));
 }
 
 void
@@ -71,6 +78,36 @@ TimingLine::timingSeparatorHasChanged(int sylIndex, qreal x)
 {
 }
 
+void
+TimingLine::sepEnterPress(int sepIndex)
+{
+}
+
+void
+TimingLine::sepExitPress(int sepIndex)
+{
+    if (tempOffset) {
+        prepareGeometryChange();
+        if (sepIndex == 0) {
+            moveBy(tempOffset, 0);
+
+            timingSyls[sepIndex]->setPos(0, 0);
+            seps[sepIndex]->silentlySetPos(0, 0);
+
+            for (int i = 1; i < timingSyls.size(); i++) {
+                timingSyls[i]->moveBy(-tempOffset, 0);
+            }
+            for (int i = 1; i < seps.size(); i++) {
+                seps[i]->silentlyMoveBy(-tempOffset, 0);
+            }
+
+            line.setStart(quint64(TimingUtils::msFromPos(mapToScene(0, 0).x()) / 10));
+        }
+    }
+
+    tempOffset = 0;
+}
+
 qreal
 TimingLine::requestMove(int sepIndex, qreal x)
 {
@@ -92,12 +129,14 @@ TimingLine::requestMove(int sepIndex, qreal x)
         if (ret > maxi)
             ret = maxi;
 
+        tempOffset = ret;
+
         quint64 dur1 = quint64(TimingUtils::msFromPos(int(seps[1]->pos().x() - ret)) / 10);
         (*syls)[0].setDuration(dur1);
         timingSyls[0]->setLen(dur1);
-        setPos(originalX + ret, originalY);
-        line.setStart(line.getStart() +
-                      quint64(TimingUtils::msFromPos(int(originalX) + int(ret) / 10)));
+        timingSyls[0]->setPos(ret, 0);
+        line.setStart(
+            quint64(TimingUtils::msFromPos(mapToScene(seps[0]->pos().x(), 0).x()) / 10));
     }
 
     else if (sepIndex >= syls->size()) {
diff --git a/src/UI/DocumentViews/AudioVisualizer/TimingLine.hh b/src/UI/DocumentViews/AudioVisualizer/TimingLine.hh
index a6116316..18e68323 100644
--- a/src/UI/DocumentViews/AudioVisualizer/TimingLine.hh
+++ b/src/UI/DocumentViews/AudioVisualizer/TimingLine.hh
@@ -20,14 +20,16 @@ private:
     Ass::Line line;
     QVector<TimingSeparator *> seps;
     QVector<TimingSyl *> timingSyls;
-    int originalX;
-    int originalY;
+
+    qreal tempOffset{ 0 };
 
 public:
     qreal requestMove(int, qreal);
 
 public slots:
     void timingSeparatorHasChanged(int, qreal);
+    void sepEnterPress(int);
+    void sepExitPress(int);
 };
 
 }
diff --git a/src/UI/DocumentViews/AudioVisualizer/TimingSeparator.cc b/src/UI/DocumentViews/AudioVisualizer/TimingSeparator.cc
index cc0ac33f..5c3e7ab4 100644
--- a/src/UI/DocumentViews/AudioVisualizer/TimingSeparator.cc
+++ b/src/UI/DocumentViews/AudioVisualizer/TimingSeparator.cc
@@ -15,6 +15,7 @@ TimingSeparator::TimingSeparator(int time, int index, SeparatorStyle style_, Tim
     , sepIndex(index)
     , parentTimingLine(parent)
 {
+    qDebug() << time;
     setPos(TimingUtils::posFromMs(time), 0);
 
     setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemSendsGeometryChanges);
@@ -63,18 +64,46 @@ TimingSeparator::paint(QPainter *painter, const QStyleOptionGraphicsItem *option
     }
 }
 
+void
+TimingSeparator::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+    emit enterPress(sepIndex);
+    QGraphicsObject::mousePressEvent(event);
+}
+
+void
+TimingSeparator::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+    emit exitPress(sepIndex);
+    QGraphicsObject::mouseReleaseEvent(event);
+}
+
+void
+TimingSeparator::silentlySetPos(int x, int y)
+{
+    inhibMove = true;
+    setPos(x, y);
+    inhibMove = false;
+}
+
+void
+TimingSeparator::silentlyMoveBy(int x, int y)
+{
+    inhibMove = true;
+    moveBy(x, y);
+    inhibMove = false;
+}
+
 QVariant
 TimingSeparator::itemChange(GraphicsItemChange change, const QVariant &value) noexcept
 {
-    if (change == ItemPositionChange) {
+    if (change == ItemPositionChange && !inhibMove) {
         qreal destination = value.toPointF().x();
         destination       = parentTimingLine->requestMove(sepIndex, destination);
 
-        if (style == SeparatorStyle::Start)
-            destination = 0;
-
         emit positionChanged(sepIndex, destination);
         return QPointF(destination, 0);
     }
+
     return QGraphicsObject::itemChange(change, value);
 }
diff --git a/src/UI/DocumentViews/AudioVisualizer/TimingSeparator.hh b/src/UI/DocumentViews/AudioVisualizer/TimingSeparator.hh
index 4d90df97..67312d0b 100644
--- a/src/UI/DocumentViews/AudioVisualizer/TimingSeparator.hh
+++ b/src/UI/DocumentViews/AudioVisualizer/TimingSeparator.hh
@@ -25,11 +25,21 @@ private:
     int sepIndex;
     TimingLine *parentTimingLine;
 
+    bool inhibMove{ false };
+
 signals:
     void positionChanged(int, qreal);
+    void enterPress(int);
+    void exitPress(int);
 
 protected:
     QVariant itemChange(GraphicsItemChange change, const QVariant &value) noexcept override;
+    void mousePressEvent(QGraphicsSceneMouseEvent *event);
+    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+
+public:
+    void silentlySetPos(int, int);
+    void silentlyMoveBy(int, int);
 };
 
 }
-- 
GitLab