From 3a7dfdb6811872ce0abc353248fb1dd55f496622 Mon Sep 17 00:00:00 2001 From: itsmattkc <34096995+itsmattkc@users.noreply.github.com> Date: Tue, 21 Jun 2022 12:23:44 -0700 Subject: [PATCH] viewer: allow showing waveform and viewer simultaneously Fixes #1959 --- app/widget/viewer/viewer.cpp | 91 +++++++++++++++++++----------------- app/widget/viewer/viewer.h | 15 ++++-- 2 files changed, 59 insertions(+), 47 deletions(-) diff --git a/app/widget/viewer/viewer.cpp b/app/widget/viewer/viewer.cpp index b769a0925..1387874ad 100644 --- a/app/widget/viewer/viewer.cpp +++ b/app/widget/viewer/viewer.cpp @@ -72,19 +72,17 @@ ViewerWidget::ViewerWidget(QWidget *parent) : record_armed_(false), recording_(false), first_requeue_watcher_(nullptr), - enable_audio_scrubbing_(true) + enable_audio_scrubbing_(true), + waveform_mode_(kWFAutomatic) { // Set up main layout QVBoxLayout* layout = new QVBoxLayout(this); layout->setMargin(0); - // Set up stacked widget to allow switching away from the viewer widget - stack_ = new QStackedWidget(); - layout->addWidget(stack_); - // Create main OpenGL-based view and sizer sizer_ = new ViewerSizer(); - stack_->addWidget(sizer_); + sizer_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + layout->addWidget(sizer_); display_widget_ = new ViewerDisplayWidget(); display_widget_->setAcceptDrops(true); @@ -114,7 +112,7 @@ ViewerWidget::ViewerWidget(QWidget *parent) : waveform_view_ = new AudioWaveformView(); ConnectTimelineView(waveform_view_, true); PassWheelEventsToScrollBar(waveform_view_); - stack_->addWidget(waveform_view_); + layout->addWidget(waveform_view_); // Create time ruler layout->addWidget(ruler()); @@ -209,7 +207,7 @@ void ViewerWidget::ConnectNodeEvent(ViewerOutput *n) connect(n, &ViewerOutput::VideoParamsChanged, this, &ViewerWidget::UpdateRendererVideoParameters); connect(n, &ViewerOutput::AudioParamsChanged, this, &ViewerWidget::UpdateRendererAudioParameters); connect(n->video_frame_cache(), &FrameHashCache::Invalidated, this, &ViewerWidget::ViewerInvalidatedVideoRange); - connect(n, &ViewerOutput::TextureInputChanged, this, &ViewerWidget::UpdateStack); + connect(n, &ViewerOutput::TextureInputChanged, this, &ViewerWidget::UpdateWaveformViewFromMode); VideoParams vp = n->GetVideoParams(); @@ -230,7 +228,7 @@ void ViewerWidget::ConnectNodeEvent(ViewerOutput *n) dw->ConnectColorManager(color_manager); } - UpdateStack(); + UpdateWaveformViewFromMode(); waveform_view_->SetViewer(GetConnectedNode()->audio_playback_cache()); waveform_view_->ConnectTimelinePoints(GetConnectedNode()->GetTimelinePoints()); @@ -253,7 +251,7 @@ void ViewerWidget::DisconnectNodeEvent(ViewerOutput *n) disconnect(n, &ViewerOutput::VideoParamsChanged, this, &ViewerWidget::UpdateRendererVideoParameters); disconnect(n, &ViewerOutput::AudioParamsChanged, this, &ViewerWidget::UpdateRendererAudioParameters); disconnect(n->video_frame_cache(), &FrameHashCache::Invalidated, this, &ViewerWidget::ViewerInvalidatedVideoRange); - disconnect(n, &ViewerOutput::TextureInputChanged, this, &ViewerWidget::UpdateStack); + disconnect(n, &ViewerOutput::TextureInputChanged, this, &ViewerWidget::UpdateWaveformViewFromMode); CloseAudioProcessor(); @@ -272,7 +270,7 @@ void ViewerWidget::DisconnectNodeEvent(ViewerOutput *n) waveform_view_->ConnectTimelinePoints(nullptr); // Queue an UpdateStack so that when it runs, the viewer node will be fully disconnected - QMetaObject::invokeMethod(this, &ViewerWidget::UpdateStack, Qt::QueuedConnection); + QMetaObject::invokeMethod(this, &ViewerWidget::UpdateWaveformViewFromMode, Qt::QueuedConnection); SetGizmos(nullptr); } @@ -543,6 +541,22 @@ void ViewerWidget::CloseAudioProcessor() audio_processor_.Close(); } +void ViewerWidget::SetWaveformMode(WaveformMode wf) +{ + waveform_mode_ = wf; + UpdateWaveformViewFromMode(); +} + +void ViewerWidget::UpdateWaveformViewFromMode() +{ + bool prefer_waveform = ShouldForceWaveform(); + + sizer_->setVisible(waveform_mode_ == kWFViewerAndWaveform || waveform_mode_ == kWFViewerOnly || (waveform_mode_ == kWFAutomatic && !prefer_waveform)); + waveform_view_->setVisible(waveform_mode_ == kWFViewerAndWaveform || waveform_mode_ == kWFWaveformOnly || (waveform_mode_ == kWFAutomatic && prefer_waveform)); + + waveform_view_->setSizePolicy(QSizePolicy::Expanding, waveform_mode_ == kWFViewerAndWaveform ? QSizePolicy::Maximum : QSizePolicy::Expanding); +} + void ViewerWidget::QueueNextAudioBuffer() { rational queue_end = audio_playback_queue_time_ + (kAudioPlaybackInterval * playback_speed_); @@ -1014,28 +1028,6 @@ int ViewerWidget::DeterminePlaybackQueueSize() return qMin(max_frames, remaining_frames); } -void ViewerWidget::UpdateStack() -{ - rational new_tb; - - if (ShouldForceWaveform()) { - // If we have a node AND video is disconnected AND audio is connected, show waveform view - stack_->setCurrentWidget(waveform_view_); - //new_tb = GetConnectedNode()->audio_params().time_base(); - } else { - // Otherwise show regular display - stack_->setCurrentWidget(sizer_); - - /*if (GetConnectedNode()) { - new_tb = GetConnectedNode()->video_params().time_base(); - }*/ - } - - /*if (new_tb != timebase()) { - SetTimebase(new_tb); - }*/ -} - void ViewerWidget::ContextMenuSetFullScreen(QAction *action) { SetFullScreen(QGuiApplication::screens().at(action->data().toInt())); @@ -1259,11 +1251,26 @@ void ViewerWidget::ShowContextMenu(const QPoint &pos) } { - QAction* show_waveform_action = menu.addAction(tr("Show Audio Waveform")); - show_waveform_action->setCheckable(true); - show_waveform_action->setChecked(stack_->currentWidget() == waveform_view_); - show_waveform_action->setEnabled(!ShouldForceWaveform()); - connect(show_waveform_action, &QAction::triggered, this, &ViewerWidget::ManualSwitchToWaveform); + auto waveform_menu = new Menu(tr("Audio Waveform"), &menu); + menu.addMenu(waveform_menu); + + auto auto_showhide = waveform_menu->addAction(tr("Automatically Show/Hide")); + auto show_waveform = waveform_menu->addAction(tr("Show Waveform Only")); + auto show_both = waveform_menu->addAction(tr("Show Both Viewer And Waveform")); + + auto_showhide->setCheckable(true); + show_waveform->setCheckable(true); + show_both->setCheckable(true); + + auto_showhide->setData(kWFAutomatic); + show_waveform->setData(kWFWaveformOnly); + show_both->setData(kWFViewerAndWaveform); + + auto_showhide->setChecked(waveform_mode_ == kWFAutomatic); + show_waveform->setChecked(waveform_mode_ == kWFWaveformOnly); + show_both->setChecked(waveform_mode_ == kWFViewerAndWaveform); + + connect(waveform_menu, &Menu::triggered, this, &ViewerWidget::UpdateWaveformModeFromMenu); } { @@ -1579,13 +1586,9 @@ void ViewerWidget::ViewerInvalidatedVideoRange(const TimeRange &range) } } -void ViewerWidget::ManualSwitchToWaveform(bool e) +void ViewerWidget::UpdateWaveformModeFromMenu(QAction *a) { - if (e) { - stack_->setCurrentWidget(waveform_view_); - } else { - stack_->setCurrentWidget(sizer_); - } + SetWaveformMode(static_cast(a->data().toInt())); } void ViewerWidget::DragEntered(QDragEnterEvent* event) diff --git a/app/widget/viewer/viewer.h b/app/widget/viewer/viewer.h index 4a879c367..86b8969c4 100644 --- a/app/widget/viewer/viewer.h +++ b/app/widget/viewer/viewer.h @@ -51,6 +51,13 @@ class ViewerWidget : public TimeBasedWidget { Q_OBJECT public: + enum WaveformMode { + kWFAutomatic, + kWFViewerOnly, + kWFWaveformOnly, + kWFViewerAndWaveform + }; + ViewerWidget(QWidget* parent = nullptr); virtual ~ViewerWidget() override; @@ -223,7 +230,7 @@ private: void CloseAudioProcessor(); - QStackedWidget* stack_; + void SetWaveformMode(WaveformMode wf); ViewerSizer* sizer_; @@ -284,6 +291,8 @@ private: bool enable_audio_scrubbing_; + WaveformMode waveform_mode_; + private slots: void PlaybackTimerUpdate(); @@ -299,7 +308,7 @@ private slots: void SetZoomFromMenu(QAction* action); - void UpdateStack(); + void UpdateWaveformViewFromMode(); void ContextMenuSetFullScreen(QAction* action); @@ -317,7 +326,7 @@ private slots: void ViewerInvalidatedVideoRange(const olive::TimeRange &range); - void ManualSwitchToWaveform(bool e); + void UpdateWaveformModeFromMenu(QAction *a); void DragEntered(QDragEnterEvent* event);