From 793b44e5dd92095919aeeba7156c4fe222624b7f Mon Sep 17 00:00:00 2001 From: Igor Korsukov <igor.korsukov@gmail.com> Date: Tue, 14 May 2024 23:01:43 +0300 Subject: [PATCH] [AU4] limiting wave drawing to the visible area --- au4/src/au3wrap/iau3wavepainter.h | 10 ++- au4/src/au3wrap/internal/au3wavepainter.cpp | 31 ++++++++-- .../ProjectScene/clipsview/ClipItem.qml | 2 + .../clipsview/TracksClipsView.qml | 62 +++++++++++-------- .../view/clipsview/clipslistmodel.cpp | 6 +- .../view/clipsview/timelinecontext.cpp | 13 +++- .../view/clipsview/timelinecontext.h | 2 + .../projectscene/view/clipsview/waveview.cpp | 38 +++++++++++- .../projectscene/view/clipsview/waveview.h | 12 +++- 9 files changed, 138 insertions(+), 38 deletions(-) diff --git a/au4/src/au3wrap/iau3wavepainter.h b/au4/src/au3wrap/iau3wavepainter.h index b7b7117b51..fe98e7d895 100644 --- a/au4/src/au3wrap/iau3wavepainter.h +++ b/au4/src/au3wrap/iau3wavepainter.h @@ -22,8 +22,16 @@ public: QColor highlight; }; + struct Geometry { + double height = 0.0; // wave view height + double width = 0.0; // wave view width + double left = 0.0; // on track line + double frameLeft = 0.0; // track line shift + double frameWidth = 0.0; // track line visible width + }; + struct Params { - QRect viewRect; + Geometry geometry; double zoom = 0.0; Style style; }; diff --git a/au4/src/au3wrap/internal/au3wavepainter.cpp b/au4/src/au3wrap/internal/au3wavepainter.cpp index 234e397656..b6e7dd6e00 100644 --- a/au4/src/au3wrap/internal/au3wavepainter.cpp +++ b/au4/src/au3wrap/internal/au3wavepainter.cpp @@ -149,6 +149,13 @@ public: auto left = targetRect.x() + leftOffset; auto height = targetRect.height(); + LOGDA() << "zoom: " << zoomInfo.GetZoom() + << " leftOffset: " << leftOffset + << " targetRect.x() : " << targetRect.x() + << " left: " << left + << " from: " << from + << " to: " << to; + const auto top = targetRect.y(); for (auto it = range.begin(); it != range.end(); ++it) { @@ -888,6 +895,7 @@ void DrawWaveform(int channelIndex, } const double t0 = params.t0; + LOGDA() << "t0: " << t0; const double sampleRate = clip.GetRate(); const double playStartTime = clip.GetPlayStartTime(); const double trackRectT0 = params.trackRectT0; @@ -1012,6 +1020,7 @@ AudacityProject& Au3WavePainter::projectRef() const void Au3WavePainter::paint(QPainter& painter, const processing::ClipKey& clipKey, const Params& params) { + LOGD() << "trackId: " << clipKey.trackId << ", clip: " << clipKey.index; WaveTrack* track = DomAccessor::findWaveTrack(projectRef(), TrackId(clipKey.trackId)); IF_ASSERT_FAILED(track) { return; @@ -1043,13 +1052,27 @@ void Au3WavePainter::doPaint(QPainter& painter, const WaveTrack* _track, const W const bool dB = !WaveformSettings::Get(*track).isLinear(); - auto top = params.viewRect.top(); - const auto channelHeight = (params.viewRect.height()) / static_cast<int>(clip->NChannels()); + const auto channelHeight = (params.geometry.height) / static_cast<int>(clip->NChannels()); + + const Geometry& g = params.geometry; + + double width = std::min(g.left + g.width, g.frameLeft + g.frameWidth) - g.left; + double left = std::min(g.left - g.frameLeft, 0.0); + double clipStartTime = clip->GetPlayStartTime();// + (left / params.zoom); + LOGDA() << "g.width: " << g.width + << " g.left: " << g.left + << " g.frameWidth: " << g.frameWidth + << " g.frameLeft: " << g.frameLeft + << " (g.left + g.width): " << (g.left + g.width) + << " (g.frameLeft + g.frameWidth): " << (g.frameLeft + g.frameWidth) + << " width: " << width + << " left: " << left; - ZoomInfo zoomInfo{ clip->GetPlayStartTime(), params.zoom }; + ZoomInfo zoomInfo(clipStartTime, params.zoom); SelectedRegion selectedRegion{}; + double top = 0.0; for (unsigned i = 0; i < clip->NChannels(); ++i) { - QRect rect = QRect(params.viewRect.left(), top, params.viewRect.width(), channelHeight); + QRect rect(0, top, width, channelHeight); DrawWaveform(i, painter, *track, *clip, zoomInfo, selectedRegion, rect, params.style, dB, track->GetMute(), false); top += channelHeight; } diff --git a/au4/src/projectscene/qml/Audacity/ProjectScene/clipsview/ClipItem.qml b/au4/src/projectscene/qml/Audacity/ProjectScene/clipsview/ClipItem.qml index eaed6cad03..94bd4f8db4 100644 --- a/au4/src/projectscene/qml/Audacity/ProjectScene/clipsview/ClipItem.qml +++ b/au4/src/projectscene/qml/Audacity/ProjectScene/clipsview/ClipItem.qml @@ -55,5 +55,7 @@ Rectangle { anchors.right: parent.right anchors.bottom: parent.bottom anchors.margins: 1 + + clipLeft: root.x } } diff --git a/au4/src/projectscene/qml/Audacity/ProjectScene/clipsview/TracksClipsView.qml b/au4/src/projectscene/qml/Audacity/ProjectScene/clipsview/TracksClipsView.qml index 5fc57a83fa..721fff7694 100644 --- a/au4/src/projectscene/qml/Audacity/ProjectScene/clipsview/TracksClipsView.qml +++ b/au4/src/projectscene/qml/Audacity/ProjectScene/clipsview/TracksClipsView.qml @@ -4,12 +4,15 @@ import Muse.UiComponents import Audacity.ProjectScene -Item { +Rectangle { id: root clip: true + //color: ui.theme.backgroundPrimaryColor + color: "#ffffff" + TracksListClipsModel { id: tracksModel } @@ -18,35 +21,42 @@ Item { tracksModel.load() } - Timeline { - id: timeline + Rectangle { + anchors.fill: parent + anchors.leftMargin: 150 + anchors.rightMargin: 150 + color: ui.theme.backgroundPrimaryColor - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - } + Timeline { + id: timeline - MouseArea { - anchors.fill: parent - onWheel: function(wheel) { - timeline.onWheel(wheel.angleDelta.y) + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + } + + MouseArea { + anchors.fill: parent + onWheel: function(wheel) { + timeline.onWheel(wheel.angleDelta.y) + } } - } - Column { - anchors.top: timeline.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - - Repeater { - model: tracksModel - delegate: TrackClipsItem { - anchors.left: parent.left - anchors.right: parent.right - height: 144 - context: timeline.context - trackId: trackIdData + Column { + anchors.top: timeline.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + + Repeater { + model: tracksModel + delegate: TrackClipsItem { + anchors.left: parent.left + anchors.right: parent.right + height: 144 + context: timeline.context + trackId: trackIdData + } } } } diff --git a/au4/src/projectscene/view/clipsview/clipslistmodel.cpp b/au4/src/projectscene/view/clipsview/clipslistmodel.cpp index dabc1f7e3d..4856435d20 100644 --- a/au4/src/projectscene/view/clipsview/clipslistmodel.cpp +++ b/au4/src/projectscene/view/clipsview/clipslistmodel.cpp @@ -91,7 +91,7 @@ QVariant ClipsListModel::data(const QModelIndex& index, int role) const bool ClipsListModel::setData(const QModelIndex& index, const QVariant& value, int role) { - LOGD() << "" << index.row() << ", value: " << value << ", role: " << role; + //LOGD() << "" << index.row() << ", value: " << value << ", role: " << role; switch (role) { case ClipLeftRole: { return changeClipStartTime(index, value); @@ -104,6 +104,10 @@ bool ClipsListModel::setData(const QModelIndex& index, const QVariant& value, in void ClipsListModel::onTimelineContextValuesChanged() { + // LOGDA() << "zoom: " << m_context->zoom() + // << " frameStartTime: " << m_context->frameStartTime() + // << " frameEndTime: " << m_context->frameEndTime(); + for (size_t i = 0; i < m_clipList.size(); ++i) { QModelIndex idx = this->index(int(i)); emit dataChanged(idx, idx, { ClipWidthRole, ClipLeftRole }); diff --git a/au4/src/projectscene/view/clipsview/timelinecontext.cpp b/au4/src/projectscene/view/clipsview/timelinecontext.cpp index 536632b4e6..6f6e6e9dda 100644 --- a/au4/src/projectscene/view/clipsview/timelinecontext.cpp +++ b/au4/src/projectscene/view/clipsview/timelinecontext.cpp @@ -37,7 +37,7 @@ void TimelineContext::onWheel(double y) void TimelineContext::changeZoom(int direction) { - double step = std::max(zoom() / 2.0, ZOOM_MIN); + double step = std::round(std::max(zoom() / 2.0, ZOOM_MIN) * 10) / 10; double _zoom = zoom() + (step * direction); _zoom = std::floor(_zoom * 10.0) / 10.0; @@ -52,8 +52,8 @@ void TimelineContext::changeZoom(int direction) void TimelineContext::onResizeFrameWidth(double frameWidth) { - setFrameEndTime(m_frameStartTime + positionToTime(frameWidth)); - emit frameTimeChanged(); + m_frameWidth = frameWidth; + updateFrameTime(); } void TimelineContext::shiftFrameTime(int direction) @@ -67,6 +67,12 @@ void TimelineContext::shiftFrameTime(int direction) emit frameTimeChanged(); } +void TimelineContext::updateFrameTime() +{ + setFrameEndTime(m_frameStartTime + positionToTime(m_frameWidth)); + emit frameTimeChanged(); +} + void TimelineContext::onSelection(double x1, double x2) { onSelectionTime(positionToTime(x1), positionToTime(x2)); @@ -110,6 +116,7 @@ void TimelineContext::setZoom(double zoom) if (m_zoom != zoom) { m_zoom = zoom; emit zoomChanged(); + updateFrameTime(); } } diff --git a/au4/src/projectscene/view/clipsview/timelinecontext.h b/au4/src/projectscene/view/clipsview/timelinecontext.h index 76bb2c1023..9524fab9ac 100644 --- a/au4/src/projectscene/view/clipsview/timelinecontext.h +++ b/au4/src/projectscene/view/clipsview/timelinecontext.h @@ -68,6 +68,7 @@ private: void shiftFrameTime(int direction); void setFrameStartTime(double newFrameStartTime); void setFrameEndTime(double newFrameEndTime); + void updateFrameTime(); void changeZoom(int direction); @@ -75,6 +76,7 @@ private: void updateSelectionActive(); void setSelectionActive(bool newSelectionActive); + double m_frameWidth = 0.0; double m_frameStartTime = 0.0; double m_frameEndTime = 0.0; diff --git a/au4/src/projectscene/view/clipsview/waveview.cpp b/au4/src/projectscene/view/clipsview/waveview.cpp index 899b1f19c0..c2ef066e9f 100644 --- a/au4/src/projectscene/view/clipsview/waveview.cpp +++ b/au4/src/projectscene/view/clipsview/waveview.cpp @@ -29,7 +29,12 @@ void WaveView::setClipKey(const ClipKey& newClipKey) void WaveView::paint(QPainter* painter) { au3::IAu3WavePainter::Params params; - params.viewRect = QRect(0, 0, width(), height()); + params.geometry.height = height(); + params.geometry.width = width(); + params.geometry.left = m_clipLeft; + params.geometry.frameLeft = m_context->frameStartTime() * m_context->zoom(); + params.geometry.frameWidth = (m_context->frameEndTime() - m_context->frameStartTime()) * m_context->zoom(); + params.zoom = m_context->zoom(); const WaveStyle& style = configuration()->waveStyle(); @@ -60,7 +65,36 @@ void WaveView::setTimelineContext(TimelineContext* newContext) return; } - //! TODO Subscribe on context props changes + if (m_context) { + disconnect(m_context, nullptr, this, nullptr); + } + m_context = newContext; + + if (m_context) { + connect(m_context, &TimelineContext::frameTimeChanged, this, &WaveView::onFrameTimeChanged); + } + emit timelineContextChanged(); } + +void WaveView::onFrameTimeChanged() +{ + update(); +} + +double WaveView::clipLeft() const +{ + return m_clipLeft; +} + +void WaveView::setClipLeft(double newClipLeft) +{ + if (qFuzzyCompare(m_clipLeft, newClipLeft)) { + return; + } + m_clipLeft = newClipLeft; + emit clipLeftChanged(); + + update(); +} diff --git a/au4/src/projectscene/view/clipsview/waveview.h b/au4/src/projectscene/view/clipsview/waveview.h index 149b9bcf86..f65913a140 100644 --- a/au4/src/projectscene/view/clipsview/waveview.h +++ b/au4/src/projectscene/view/clipsview/waveview.h @@ -17,6 +17,11 @@ class WaveView : public QQuickPaintedItem Q_PROPERTY(TimelineContext * context READ timelineContext WRITE setTimelineContext NOTIFY timelineContextChanged FINAL) Q_PROPERTY(ClipKey clipKey READ clipKey WRITE setClipKey NOTIFY clipKeyChanged FINAL) + //! NOTE In a static position, the slip start time corresponds, + //! but it can change while dragging the clip, with the not changing start time + //! (until the end of dragging) + Q_PROPERTY(double clipLeft READ clipLeft WRITE setClipLeft NOTIFY clipLeftChanged FINAL) + muse::Inject<au3::IAu3WavePainter> wavePainter; muse::Inject<IProjectSceneConfiguration> configuration; @@ -28,17 +33,22 @@ public: void setClipKey(const ClipKey& newClipKey); TimelineContext* timelineContext() const; void setTimelineContext(TimelineContext* newContext); + double clipLeft() const; + void setClipLeft(double newClipLeft); void paint(QPainter* painter) override; signals: void clipKeyChanged(); void timelineContextChanged(); + void clipLeftChanged(); private: - void UpdateItemsCache(TimelineContext& trackPanelView); + + void onFrameTimeChanged(); ClipKey m_clipKey; TimelineContext* m_context = nullptr; + double m_clipLeft = 0; }; } -- GitLab