From 29723cc1c44a698d824983caed6c048439619d5e Mon Sep 17 00:00:00 2001
From: Elliu <elliu@hashi.re>
Date: Fri, 28 Jan 2022 22:13:49 +0100
Subject: [PATCH] Only show selected lines on audioVisualizer + FMT

---
 src/UI/DocumentViews/AssLinesView.cc          |  6 ++++
 src/UI/DocumentViews/AssLinesView.hh          |  4 +++
 src/UI/DocumentViews/AudioVisualizer.cc       |  7 ++--
 src/UI/DocumentViews/AudioVisualizer.hh       |  3 +-
 .../AudioVisualizer/TimingLine.cc             | 30 ++++++++++++-----
 .../AudioVisualizer/TimingLine.hh             |  2 +-
 .../AudioVisualizer/TimingScene.cc            | 33 ++++++++++++++++---
 .../AudioVisualizer/TimingScene.hh            | 12 ++++++-
 .../AudioVisualizer/TimingSeparator.cc        | 24 +++++---------
 .../AudioVisualizer/TimingSeparator.hh        |  9 ++---
 .../AudioVisualizer/TimingSyl.cc              |  4 +--
 src/UI/MainWindow.cc                          | 18 +++++-----
 src/UI/MainWindow.hh                          |  2 +-
 src/UI/ScriptDocumentView.hh                  |  2 +-
 src/UI/VivyDocumentView.cc                    |  3 +-
 src/UI/VivyDocumentView.hh                    |  9 ++++-
 16 files changed, 113 insertions(+), 55 deletions(-)

diff --git a/src/UI/DocumentViews/AssLinesView.cc b/src/UI/DocumentViews/AssLinesView.cc
index 022b8cfd..8df19318 100644
--- a/src/UI/DocumentViews/AssLinesView.cc
+++ b/src/UI/DocumentViews/AssLinesView.cc
@@ -46,6 +46,12 @@ AssLinesView::mouseMoveEvent(QMouseEvent *event) noexcept
     emit hoverIndexChanged(index);
 }
 
+void
+AssLinesView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
+{
+    emit updateSelectedLines(selected, deselected);
+}
+
 AssLinesView::Delegate::Delegate(AssLinesView *view, QWidget *parent) noexcept
     : QStyledItemDelegate(parent)
     , tableView(view)
diff --git a/src/UI/DocumentViews/AssLinesView.hh b/src/UI/DocumentViews/AssLinesView.hh
index 635b320c..2a3db7e0 100644
--- a/src/UI/DocumentViews/AssLinesView.hh
+++ b/src/UI/DocumentViews/AssLinesView.hh
@@ -42,7 +42,11 @@ public:
 private:
     void mouseMoveEvent(QMouseEvent *) noexcept override;
 
+protected slots:
+    virtual void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
+
 signals:
     void hoverIndexChanged(QModelIndex);
+    void updateSelectedLines(const QItemSelection &selected, const QItemSelection &deselected);
 };
 }
diff --git a/src/UI/DocumentViews/AudioVisualizer.cc b/src/UI/DocumentViews/AudioVisualizer.cc
index c5c5e69f..74df942f 100644
--- a/src/UI/DocumentViews/AudioVisualizer.cc
+++ b/src/UI/DocumentViews/AudioVisualizer.cc
@@ -5,9 +5,10 @@ using namespace Vivy;
 
 #define MAXPIXVALUE 7 // Some magix AV magic stuff
 
-AudioVisualizer::AudioVisualizer(AudioContext::StreamPtr stream, std::weak_ptr<VivyDocumentView> rootView_, QWidget *parent)
+AudioVisualizer::AudioVisualizer(AudioContext::StreamPtr stream,
+                                 std::weak_ptr<VivyDocumentView> rootView_, QWidget *parent)
     : QWidget(parent)
-      , rootView(rootView_)
+    , rootView(rootView_)
     , audioStream(stream)
 {
     if (!audioStream->isDecoded()) {
@@ -68,7 +69,7 @@ AudioVisualizer::AudioVisualizer(AudioContext::StreamPtr stream, std::weak_ptr<V
 void
 AudioVisualizer::printSpectrum(QImage pixmap, AudioContext::StreamPtr stream) noexcept
 {
-    TimingScene *timingScene = new TimingScene(pixmap, stream, this);
+    TimingScene *timingScene = new TimingScene(pixmap, stream, rootView, this);
     TimingView *timingView   = new TimingView(timingScene, pixmap, stream, this);
     TimingParams *params     = new TimingParams(this);
 
diff --git a/src/UI/DocumentViews/AudioVisualizer.hh b/src/UI/DocumentViews/AudioVisualizer.hh
index 646a48f2..3c169ac9 100644
--- a/src/UI/DocumentViews/AudioVisualizer.hh
+++ b/src/UI/DocumentViews/AudioVisualizer.hh
@@ -37,7 +37,8 @@ private:
     using RDFTContextPtr = std::unique_ptr<RDFTContext, decltype(rdftContextDeleter)>;
 
 public:
-    explicit AudioVisualizer(AudioContext::StreamPtr, std::weak_ptr<VivyDocumentView> rootView, QWidget *parent = nullptr);
+    explicit AudioVisualizer(AudioContext::StreamPtr, std::weak_ptr<VivyDocumentView> rootView,
+                             QWidget *parent = nullptr);
     ~AudioVisualizer() noexcept override = default;
 
 public slots:
diff --git a/src/UI/DocumentViews/AudioVisualizer/TimingLine.cc b/src/UI/DocumentViews/AudioVisualizer/TimingLine.cc
index 3c0b28d5..e4316254 100644
--- a/src/UI/DocumentViews/AudioVisualizer/TimingLine.cc
+++ b/src/UI/DocumentViews/AudioVisualizer/TimingLine.cc
@@ -11,19 +11,27 @@ using namespace Vivy;
 
 TimingLine::TimingLine(Ass::Line *lineptr, QGraphicsItem *parent)
     : QGraphicsObject(parent)
-      , line(*lineptr)
+    , line(*lineptr)
 {
-    setPos(TimingUtils::posFromMs(int(line.getStart())*10), TimingUtils::axisHeight());
-    int currentTime = 0;
+    setPos(TimingUtils::posFromMs(int(line.getStart()) * 10), TimingUtils::axisHeight());
+    int currentTime        = 0;
     QVector<Ass::Syl> syls = line.getContent();
-    for (int i = 0; i < syls.size(); ++i){
+    for (int i = 0; i < syls.size(); ++i) {
         int endSyl = currentTime + 10 * int(syls.at(i).getDuration());
 
-        TimingSyl* timingSyl = new TimingSyl(syls.at(i), currentTime, this);
+        TimingSyl *timingSyl = new TimingSyl(syls.at(i), currentTime, this);
 
         // TODO: Here create the TimingSeparator and connect
-        TimingSeparator* timingSeparatorStart = new TimingSeparator(currentTime, i != 0 ? TimingSeparator::SeparatorStyle::Middle : TimingSeparator::SeparatorStyle::Start, this);
-        TimingSeparator* timingSeparatorEnd = new TimingSeparator(i != syls.size()-1 ? endSyl : int(10*line.getDuration()), i != syls.size()-1 ? TimingSeparator::SeparatorStyle::Middle : TimingSeparator::SeparatorStyle::End, this);
+        TimingSeparator *timingSeparatorStart =
+            new TimingSeparator(currentTime,
+                                i != 0 ? TimingSeparator::SeparatorStyle::Middle
+                                       : TimingSeparator::SeparatorStyle::Start,
+                                this);
+        TimingSeparator *timingSeparatorEnd =
+            new TimingSeparator(i != syls.size() - 1 ? endSyl : int(10 * line.getDuration()),
+                                i != syls.size() - 1 ? TimingSeparator::SeparatorStyle::Middle
+                                                     : TimingSeparator::SeparatorStyle::End,
+                                this);
 
         currentTime = endSyl;
     }
@@ -32,11 +40,15 @@ TimingLine::TimingLine(Ass::Line *lineptr, QGraphicsItem *parent)
 QRectF
 TimingLine::boundingRect() const
 {
-    return QRectF(0, 0, TimingUtils::posFromMs(int(10*(line.getEnd()-line.getStart()))), TimingUtils::audioHeight());
+    return QRectF(0, 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(0, 0,
+                             TimingUtils::posFromMs(int(10 * (line.getEnd() - line.getStart()))),
+                             TimingUtils::audioHeight()),
+                      QColor(0, 255, 255, 50));
 }
diff --git a/src/UI/DocumentViews/AudioVisualizer/TimingLine.hh b/src/UI/DocumentViews/AudioVisualizer/TimingLine.hh
index 6b8be066..ea7c7f86 100644
--- a/src/UI/DocumentViews/AudioVisualizer/TimingLine.hh
+++ b/src/UI/DocumentViews/AudioVisualizer/TimingLine.hh
@@ -9,7 +9,7 @@ namespace Vivy
 class TimingLine final : public QGraphicsObject {
     Q_OBJECT
 public:
-    explicit TimingLine(Ass::Line*, QGraphicsItem* = nullptr);
+    explicit TimingLine(Ass::Line *, QGraphicsItem * = nullptr);
 
     QRectF boundingRect() const override;
     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
diff --git a/src/UI/DocumentViews/AudioVisualizer/TimingScene.cc b/src/UI/DocumentViews/AudioVisualizer/TimingScene.cc
index 53ea04fc..f602b328 100644
--- a/src/UI/DocumentViews/AudioVisualizer/TimingScene.cc
+++ b/src/UI/DocumentViews/AudioVisualizer/TimingScene.cc
@@ -22,7 +22,6 @@
 
 #include "TimingAxis.hh"
 #include "TimingCursor.hh"
-#include "TimingLine.hh"
 
 using namespace Vivy;
 
@@ -31,12 +30,21 @@ TimingScene::TimingScene(QWidget *parent) noexcept
 {
 }
 
-TimingScene::TimingScene(QImage img_, AudioContext::StreamPtr stream, QWidget *parent) noexcept
+TimingScene::TimingScene(QImage img_, AudioContext::StreamPtr stream,
+                         std::weak_ptr<VivyDocumentView> rootView_, QWidget *parent) noexcept
     : QGraphicsScene(parent)
+    , rootView(rootView_)
     , img(img_)
     , audioStream(stream)
 {
     rebuildScene();
+
+    if (auto p = rootView.lock()) {
+        if (auto assLinesView = p->getAssLinesView()) {
+            connect(assLinesView, &AssLinesView::updateSelectedLines, this,
+                    &TimingScene::updateSelectedLines);
+        }
+    }
 }
 
 void
@@ -54,6 +62,7 @@ TimingScene::rebuildScene()
         removeItem(item);
         delete (item);
     }
+    timingLines.clear();
 
     // We put a common origin for the items at the bottom of the axis
     TimingUtils::setAxisHeight(30); // TODO: remove magic number
@@ -81,8 +90,10 @@ TimingScene::rebuildScene()
         QVector<Ass::LinePtr> lines = assDocument->getLines();
         for (int i = 0; i < lines.size(); ++i) {
             if (auto line = lines.at(i).get()) {
-                TimingLine* timingLine = new TimingLine(line);
-                addItem(timingLine);
+                TimingLine *l = new TimingLine(line);
+                l->setVisible(false);
+                addItem(l);
+                timingLines.append(l);
                 // TODO: Here connect timingLine.linechanged to lineassmodel or something
             }
         }
@@ -151,3 +162,17 @@ TimingScene::getAxis()
 {
     return ax;
 }
+
+void
+TimingScene::updateSelectedLines(const QItemSelection &selected, const QItemSelection &deselected)
+{
+    auto indexes = selected.indexes();
+    for (int i = 0; i < indexes.size(); ++i) {
+        timingLines[indexes[i].row()]->setVisible(true);
+    }
+
+    indexes = deselected.indexes();
+    for (int i = 0; i < indexes.size(); ++i) {
+        timingLines[indexes[i].row()]->setVisible(false);
+    }
+}
diff --git a/src/UI/DocumentViews/AudioVisualizer/TimingScene.hh b/src/UI/DocumentViews/AudioVisualizer/TimingScene.hh
index bfa2f3ba..df331c07 100644
--- a/src/UI/DocumentViews/AudioVisualizer/TimingScene.hh
+++ b/src/UI/DocumentViews/AudioVisualizer/TimingScene.hh
@@ -6,6 +6,11 @@
 #include "TimingAxis.hh"
 #include "TimingCursor.hh"
 
+#include "../../VivyDocumentView.hh"
+#include "../AssLinesView.hh"
+
+#include "TimingLine.hh"
+
 namespace Vivy
 {
 class TimingScene final : public QGraphicsScene {
@@ -20,9 +25,11 @@ public:
     static inline constexpr QColor endColour   = QColor(0, 127, 0);
 
     explicit TimingScene(QWidget *parent = nullptr) noexcept;
-    explicit TimingScene(QImage, AudioContext::StreamPtr, QWidget * = nullptr) noexcept;
+    explicit TimingScene(QImage, AudioContext::StreamPtr, std::weak_ptr<VivyDocumentView>,
+                         QWidget * = nullptr) noexcept;
 
 private:
+    std::weak_ptr<VivyDocumentView> rootView;
     QGraphicsPixmapItem *backgroundImg{ nullptr };
     QImage img;
     TimingCursor *cursor;
@@ -31,6 +38,8 @@ private:
     TimingMode timingMode{ TimingMode::Line };
     TimingAxis *ax{ nullptr };
 
+    QVector<TimingLine *> timingLines;
+
 public:
     QGraphicsPixmapItem *bg() noexcept;
     void mousePressEvent(QGraphicsSceneMouseEvent *event) noexcept override;
@@ -49,6 +58,7 @@ private:
 
 public slots:
     void updateScene(QImage, AudioContext::StreamPtr);
+    void updateSelectedLines(const QItemSelection &selected, const QItemSelection &deselected);
     void rebuildScene();
 };
 
diff --git a/src/UI/DocumentViews/AudioVisualizer/TimingSeparator.cc b/src/UI/DocumentViews/AudioVisualizer/TimingSeparator.cc
index aae1083b..e8811d4d 100644
--- a/src/UI/DocumentViews/AudioVisualizer/TimingSeparator.cc
+++ b/src/UI/DocumentViews/AudioVisualizer/TimingSeparator.cc
@@ -7,22 +7,16 @@
 
 using namespace Vivy;
 
-TimingSeparator::TimingSeparator(int time, SeparatorStyle style_, QGraphicsItem* parent)
+TimingSeparator::TimingSeparator(int time, SeparatorStyle style_, QGraphicsItem *parent)
     : QGraphicsObject(parent)
     , style(style_)
 {
     setPos(TimingUtils::posFromMs(time), 0);
 
-    switch(style){
-    case SeparatorStyle::Start:
-        pen = QPen(QColor(0, 0, 255));
-        break;
-    case SeparatorStyle::Middle:
-        pen = QPen(QColor(180, 0, 180));
-        break;
-    case SeparatorStyle::End:
-        pen = QPen(QColor(255, 0, 0));
-        break;
+    switch (style) {
+    case SeparatorStyle::Start: pen = QPen(QColor(0, 0, 255)); break;
+    case SeparatorStyle::Middle: pen = QPen(QColor(180, 0, 180)); break;
+    case SeparatorStyle::End: pen = QPen(QColor(255, 0, 0)); break;
     }
     // Putting even-size width seems to be undefined behaviour for pixel drawing : stick to odd
     pen.setWidth(1);
@@ -31,7 +25,7 @@ TimingSeparator::TimingSeparator(int time, SeparatorStyle style_, QGraphicsItem*
 QRectF
 TimingSeparator::boundingRect() const
 {
-    return QRectF(-widthPaw, 0, 2*widthPaw, TimingUtils::audioHeight());
+    return QRectF(-widthPaw, 0, 2 * widthPaw, TimingUtils::audioHeight());
 }
 
 void
@@ -40,12 +34,12 @@ TimingSeparator::paint(QPainter *painter, const QStyleOptionGraphicsItem *option
     painter->setPen(pen);
     int height = TimingUtils::audioHeight();
 
-    int top = 1 + pen.width()/2;
-    int bottom = height - 1 - pen.width()/2;
+    int top    = 1 + pen.width() / 2;
+    int bottom = height - 1 - pen.width() / 2;
 
     painter->drawLine(0, top, 0, bottom);
 
-    switch(style){
+    switch (style) {
     case SeparatorStyle::Start:
         painter->drawLine(0, top, widthPaw, top);
         painter->drawLine(0, bottom, widthPaw, bottom);
diff --git a/src/UI/DocumentViews/AudioVisualizer/TimingSeparator.hh b/src/UI/DocumentViews/AudioVisualizer/TimingSeparator.hh
index 72d648c7..61fdd95b 100644
--- a/src/UI/DocumentViews/AudioVisualizer/TimingSeparator.hh
+++ b/src/UI/DocumentViews/AudioVisualizer/TimingSeparator.hh
@@ -7,14 +7,11 @@ namespace Vivy
 class TimingSeparator final : public QGraphicsObject {
     Q_OBJECT
 public:
-    enum class SeparatorStyle {
-        Start,
-        Middle,
-        End
-    };
+    enum class SeparatorStyle { Start, Middle, End };
 
 public:
-    explicit TimingSeparator(int, SeparatorStyle style = SeparatorStyle::Middle, QGraphicsItem *parent = nullptr);
+    explicit TimingSeparator(int, SeparatorStyle style = SeparatorStyle::Middle,
+                             QGraphicsItem *parent = nullptr);
 
     QRectF boundingRect() const override;
     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
diff --git a/src/UI/DocumentViews/AudioVisualizer/TimingSyl.cc b/src/UI/DocumentViews/AudioVisualizer/TimingSyl.cc
index 80ec74e1..548324fa 100644
--- a/src/UI/DocumentViews/AudioVisualizer/TimingSyl.cc
+++ b/src/UI/DocumentViews/AudioVisualizer/TimingSyl.cc
@@ -10,7 +10,7 @@ using namespace Vivy;
 
 TimingSyl::TimingSyl(Ass::Syl syl_, int startTime, QGraphicsItem *parent)
     : QGraphicsObject(parent)
-      , syl(syl_)
+    , syl(syl_)
 {
     setPos(TimingUtils::posFromMs(startTime), 0);
 }
@@ -18,7 +18,7 @@ TimingSyl::TimingSyl(Ass::Syl syl_, int startTime, QGraphicsItem *parent)
 QRectF
 TimingSyl::boundingRect() const
 {
-    return QRectF(0, 0, int(syl.getDuration()),TimingUtils::audioHeight());
+    return QRectF(0, 0, int(syl.getDuration()), TimingUtils::audioHeight());
 }
 
 void
diff --git a/src/UI/MainWindow.cc b/src/UI/MainWindow.cc
index dffe9740..fc9f6239 100644
--- a/src/UI/MainWindow.cc
+++ b/src/UI/MainWindow.cc
@@ -21,16 +21,15 @@
 
 #define ACTION_ADD_SHORTCUT(action, shortcut) action##Act->setShortcut(shortcut);
 
-#define ADD_TAB(view) \
-    std::shared_ptr<AbstractDocumentView> viewPtr; \
-    viewPtr.reset(view); \
-    if (auto p = viewPtr.get()) { \
-        p->loadViews(); \
+#define ADD_TAB(view)                                    \
+    std::shared_ptr<AbstractDocumentView> viewPtr;       \
+    viewPtr.reset(view);                                 \
+    if (auto p = viewPtr.get()) {                        \
+        p->loadViews();                                  \
         documentViewPtrs.insert(viewPtr.get(), viewPtr); \
-        addTab(p); \
+        addTab(p);                                       \
     }
 
-
 using namespace Vivy;
 
 MainWindow::MainWindow() noexcept
@@ -347,8 +346,9 @@ MainWindow::openDocument() noexcept
 
     // Handle the different types here
     try {
-        if (fileType == Utils::DocumentType::Vivy){
-            ADD_TAB(new VivyDocumentView(vivyApp->documentStore->loadDocument(filename), documents));
+        if (fileType == Utils::DocumentType::Vivy) {
+            ADD_TAB(
+                new VivyDocumentView(vivyApp->documentStore->loadDocument(filename), documents));
         }
 
         else if (fileType == Utils::DocumentType::VivyScript) {
diff --git a/src/UI/MainWindow.hh b/src/UI/MainWindow.hh
index b8738dc4..3f66108a 100644
--- a/src/UI/MainWindow.hh
+++ b/src/UI/MainWindow.hh
@@ -96,7 +96,7 @@ private:
         }
     }
 
-    QMap<AbstractDocumentView*,std::shared_ptr<AbstractDocumentView>> documentViewPtrs;
+    QMap<AbstractDocumentView *, std::shared_ptr<AbstractDocumentView>> documentViewPtrs;
 
 protected:
     void closeEvent(QCloseEvent *) noexcept override;
diff --git a/src/UI/ScriptDocumentView.hh b/src/UI/ScriptDocumentView.hh
index 8d45158b..67090fb3 100644
--- a/src/UI/ScriptDocumentView.hh
+++ b/src/UI/ScriptDocumentView.hh
@@ -34,7 +34,7 @@ public:
     QIcon getDocumentTabIcon() const noexcept override;
     AbstractDocument *getDocument() const noexcept override;
 
-    void loadViews() noexcept override {} ;
+    void loadViews() noexcept override{};
 
     void setUseFakeVimEditor(bool yes) noexcept;
 
diff --git a/src/UI/VivyDocumentView.cc b/src/UI/VivyDocumentView.cc
index b1b4eb3b..0e977afe 100644
--- a/src/UI/VivyDocumentView.cc
+++ b/src/UI/VivyDocumentView.cc
@@ -45,7 +45,8 @@ VivyDocumentView::VivyDocumentView(std::shared_ptr<VivyDocument> doc, QWidget *p
     VIVY_LOG_CTOR() << "View for " << doc->getUuid() << " done!";
 }
 
-void VivyDocumentView::loadViews() noexcept
+void
+VivyDocumentView::loadViews() noexcept
 {
     loadAudioView();
     loadVideoView();
diff --git a/src/UI/VivyDocumentView.hh b/src/UI/VivyDocumentView.hh
index bc777451..ea6b8bfd 100644
--- a/src/UI/VivyDocumentView.hh
+++ b/src/UI/VivyDocumentView.hh
@@ -16,7 +16,8 @@
 
 namespace Vivy
 {
-class VivyDocumentView final : public AbstractDocumentView, public std::enable_shared_from_this<VivyDocumentView> {
+class VivyDocumentView final : public AbstractDocumentView,
+                               public std::enable_shared_from_this<VivyDocumentView> {
     Q_OBJECT
     VIVY_UNMOVABLE_OBJECT(VivyDocumentView)
     VIVY_APP_LOGGABLE_OBJECT(VivyDocumentView, logger)
@@ -56,5 +57,11 @@ private:
     UnclosableDockWidget *assLines{ nullptr };
     UnclosableDockWidget *videoView{ nullptr };
     QAction *openPropertiesAct{ nullptr };
+
+public:
+    AssLinesView *getAssLinesView() const noexcept
+    {
+        return assLines == nullptr ? nullptr : reinterpret_cast<AssLinesView *>(assLines->widget());
+    }
 };
 }
-- 
GitLab