LCOV - code coverage report
Current view: top level - src/notationscene/qml/MuseScore/NotationScene - timelineview.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 0.0 % 83 0
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-Studio-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2021 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : 
      23              : #include "timelineview.h"
      24              : 
      25              : #include <QApplication>
      26              : #include <QQuickWindow>
      27              : #include <QSplitter>
      28              : #include <QTimer>
      29              : 
      30              : #include "notation/inotationinteraction.h" // IWYU pragma: keep
      31              : #include "notation/inotationundostack.h" // IWYU pragma: keep
      32              : 
      33              : #include "widgets/timeline.h"
      34              : 
      35              : namespace mu::notation {
      36              : class TimelineAdapter : public QSplitter, public muse::uicomponents::IDisplayableWidget
      37              : {
      38              : public:
      39            0 :     TimelineAdapter(const muse::modularity::ContextPtr& iocCtx)
      40            0 :         : QSplitter(nullptr)
      41              :     {
      42            0 :         setFocusPolicy(Qt::NoFocus);
      43            0 :         setHandleWidth(0);
      44            0 :         setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
      45            0 :         setObjectName("TimelineAdapter");
      46              : 
      47            0 :         m_msTimeline = new Timeline(this, iocCtx);
      48            0 :     }
      49              : 
      50            0 :     void updateView()
      51              :     {
      52            0 :         m_msTimeline->updateGridFromCmdState();
      53            0 :     }
      54              : 
      55            0 :     void setNotation(INotationPtr notation)
      56              :     {
      57            0 :         m_msTimeline->setNotation(notation);
      58            0 :     }
      59              : 
      60              : private:
      61            0 :     QWidget* qWidget() override
      62              :     {
      63            0 :         return this;
      64              :     }
      65              : 
      66            0 :     bool handleEvent(QEvent* e) override
      67              :     {
      68            0 :         if (QMouseEvent* me = dynamic_cast<QMouseEvent*>(e)) {
      69            0 :             return handleMouseEvent(me);
      70              :         }
      71              : 
      72            0 :         return m_msTimeline->handleEvent(e);
      73              :     }
      74              : 
      75            0 :     bool handleMouseEvent(QMouseEvent* event)
      76              :     {
      77            0 :         QPoint pos = event ? event->pos() : QPoint();
      78              : 
      79            0 :         if (event->type() == QEvent::MouseButtonPress) {
      80            0 :             m_mouseDownWidget = childAt(pos);
      81            0 :         } else if (event->type() == QEvent::MouseButtonRelease) {
      82            0 :             m_mouseDownWidget = nullptr;
      83              :         }
      84              : 
      85            0 :         bool result = false;
      86              : 
      87            0 :         if (QWidget* receiver = m_mouseDownWidget ? m_mouseDownWidget : childAt(pos)) {
      88            0 :             QMouseEvent mappedEvent(event->type(), receiver->mapFrom(this, event->position()),
      89            0 :                                     event->scenePosition(), event->globalPosition(),
      90              :                                     event->button(), event->buttons(), event->modifiers(),
      91            0 :                                     event->source(), event->pointingDevice());
      92            0 :             result = qApp->notify(receiver, &mappedEvent);
      93            0 :             event->setAccepted(mappedEvent.isAccepted());
      94            0 :         }
      95              : 
      96            0 :         return result;
      97              :     }
      98              : 
      99              :     Timeline* m_msTimeline = nullptr;
     100              :     QWidget* m_mouseDownWidget = nullptr;
     101              : };
     102              : }
     103              : 
     104              : using namespace mu::notation;
     105              : 
     106            0 : TimelineView::TimelineView(QQuickItem* parent)
     107            0 :     : WidgetView(parent), muse::Contextable(muse::iocCtxForQmlObject(this))
     108              : {
     109            0 :     m_drawTimer.setSingleShot(true);
     110            0 :     m_drawTimer.setInterval(32); // 30 fps
     111              : 
     112            0 :     connect(&m_drawTimer, &QTimer::timeout, this, &TimelineView::doDraw);
     113              : 
     114            0 :     doDraw();
     115            0 : }
     116              : 
     117            0 : void TimelineView::doDraw()
     118              : {
     119            0 :     if (isVisible()) {
     120            0 :         m_dpr =  window() ? window()->devicePixelRatio() : 1.0;
     121              : 
     122            0 :         m_image = QImage(width() * m_dpr, height() * m_dpr, QImage::Format_ARGB32_Premultiplied);
     123            0 :         m_image.setDevicePixelRatio(m_dpr);
     124            0 :         m_image.fill(Qt::transparent);
     125              : 
     126            0 :         if (qWidget()) {
     127            0 :             qWidget()->render(&m_image, QPoint(), QRegion(), QWidget::DrawWindowBackground | QWidget::DrawChildren);
     128              :         }
     129              : 
     130            0 :         update();
     131              :     }
     132              : 
     133            0 :     m_drawTimer.start();
     134            0 : }
     135              : 
     136            0 : void TimelineView::paint(QPainter* painter)
     137              : {
     138            0 :     painter->drawImage(0, 0, m_image);
     139            0 : }
     140              : 
     141            0 : void TimelineView::componentComplete()
     142              : {
     143            0 :     WidgetView::componentComplete();
     144              : 
     145            0 :     auto timeline = std::make_shared<TimelineAdapter>(iocContext());
     146              : 
     147            0 :     auto updateView = [this, timeline]() {
     148            0 :         update();
     149              : 
     150            0 :         if (timeline) {
     151            0 :             timeline->updateView();
     152              :         }
     153            0 :     };
     154              : 
     155            0 :     auto initTimeline = [this, updateView, timeline] {
     156            0 :         INotationPtr notation = projectSession()->currentNotation();
     157            0 :         timeline->setNotation(notation);
     158              : 
     159            0 :         updateView();
     160              : 
     161            0 :         if (!notation) {
     162            0 :             return;
     163              :         }
     164              : 
     165            0 :         notation->undoStack()->stackChanged().onNotify(this, [=] {
     166            0 :             updateView();
     167            0 :         }, Asyncable::Mode::SetReplace /* FIXME */);
     168              : 
     169            0 :         notation->interaction()->selectionChanged().onNotify(this, [=] {
     170            0 :             updateView();
     171            0 :         }, Asyncable::Mode::SetReplace /* FIXME */);
     172            0 :     };
     173              : 
     174            0 :     projectSession()->currentNotationChanged().onNotify(this, [initTimeline]() {
     175            0 :         initTimeline();
     176            0 :     });
     177              : 
     178            0 :     setWidget(timeline);
     179              : 
     180            0 :     initTimeline();
     181            0 : }
        

Generated by: LCOV version 2.0-1