diff --git a/app/widget/timelinewidget/timelinewidget.cpp b/app/widget/timelinewidget/timelinewidget.cpp index 04ec0876e..47c704a76 100644 --- a/app/widget/timelinewidget/timelinewidget.cpp +++ b/app/widget/timelinewidget/timelinewidget.cpp @@ -66,7 +66,8 @@ TimelineWidget::TimelineWidget(QWidget *parent) : rubberband_(QRubberBand::Rectangle, this), active_tool_(nullptr), use_audio_time_units_(false), - subtitle_show_command_(nullptr) + subtitle_show_command_(nullptr), + subtitle_tentative_track_(nullptr) { QVBoxLayout* vert_layout = new QVBoxLayout(this); vert_layout->setSpacing(0); @@ -91,13 +92,13 @@ TimelineWidget::TimelineWidget(QWidget *parent) : vert_layout->addWidget(view_splitter_); // Video view - views_.append(new TimelineAndTrackView(Qt::AlignBottom)); + views_.append(AddTimelineAndTrackView(Qt::AlignBottom)); // Audio view - views_.append(new TimelineAndTrackView(Qt::AlignTop)); + views_.append(AddTimelineAndTrackView(Qt::AlignTop)); // Subtitle view - views_.append(new TimelineAndTrackView(Qt::AlignTop)); + views_.append(AddTimelineAndTrackView(Qt::AlignTop)); // Create tools tools_.resize(olive::Tool::kCount); @@ -780,6 +781,44 @@ void TimelineWidget::DisableRecordingOverlay() } } +void TimelineWidget::AddTentativeSubtitleTrack() +{ + if (!subtitle_show_command_) { + // Determine if we need to do anything + QList sz = view_splitter_->sizes(); + bool should_adjust_splitter = (sz[Track::kSubtitle] == 0); + bool should_add_sub_track = (sequence() && sequence()->track_list(Track::kSubtitle)->GetTrackCount() == 0); + + if (should_adjust_splitter || should_add_sub_track) { + // Create command + subtitle_show_command_ = new MultiUndoCommand(); + + if (should_adjust_splitter) { + sz[Track::kSubtitle] = height() / Track::kCount; + subtitle_show_command_->add_child(new SetSplitterSizesCommand(view_splitter_, sz)); + } + + if (should_add_sub_track) { + TimelineAddTrackCommand *track_add_cmd = new TimelineAddTrackCommand(sequence()->track_list(Track::kSubtitle)); + subtitle_tentative_track_ = track_add_cmd->track(); + subtitle_show_command_->add_child(track_add_cmd); + } + + subtitle_show_command_->redo_now(); + } + } +} + +void TimelineWidget::ClearTentativeSubtitleTrack() +{ + if (subtitle_show_command_) { + subtitle_show_command_->undo_now(); + delete subtitle_show_command_; + subtitle_show_command_ = nullptr; + subtitle_tentative_track_ = nullptr; + } +} + void TimelineWidget::InsertGapsAt(const rational &earliest_point, const rational &insert_length, MultiUndoCommand *command) { for (int i=0;itool() == Tool::kAdd && Core::instance()->GetSelectedAddableObject() == Tool::kAddableSubtitle) { - if (!subtitle_show_command_) { - // Determine if we need to do anything - QList sz = view_splitter_->sizes(); - bool should_adjust_splitter = (sz[Track::kSubtitle] == 0); - bool should_add_sub_track = (sequence() && sequence()->track_list(Track::kSubtitle)->GetTrackCount() == 0); - - if (should_adjust_splitter || should_add_sub_track) { - // Create command - subtitle_show_command_ = new MultiUndoCommand(); - - if (should_adjust_splitter) { - sz[Track::kSubtitle] = height() / Track::kCount; - subtitle_show_command_->add_child(new SetSplitterSizesCommand(view_splitter_, sz)); - } - - if (should_add_sub_track) { - subtitle_show_command_->add_child(new TimelineAddTrackCommand(sequence()->track_list(Track::kSubtitle))); - } - - subtitle_show_command_->redo_now(); - } - } - } else if (subtitle_show_command_) { - subtitle_show_command_->undo_now(); - delete subtitle_show_command_; - subtitle_show_command_ = nullptr; + AddTentativeSubtitleTrack(); + } else { + ClearTentativeSubtitleTrack(); } } @@ -1210,6 +1226,16 @@ void TimelineWidget::RenameSelectedBlocks() Core::instance()->undo_stack()->pushIfHasChildren(command); } +void TimelineWidget::TrackAboutToBeDeleted(Track *track) +{ + if (track == subtitle_tentative_track_) { + // User is deleting the tentative subtitle track. Technically they shouldn't do this, but they + // might if they misinterpret it as permanent. If so, we handle it cleanly by pushing our + // command as if the action really were permanent. + Core::instance()->undo_stack()->push(TakeSubtitleSectionCommand()); + } +} + void TimelineWidget::AddGhost(TimelineViewGhostItem *ghost) { ghost_items_.append(ghost); @@ -1641,6 +1667,13 @@ bool TimelineWidget::PasteInternal(bool insert) return true; } +TimelineAndTrackView *TimelineWidget::AddTimelineAndTrackView(Qt::Alignment alignment) +{ + TimelineAndTrackView *v = new TimelineAndTrackView(alignment); + connect(v->track_view(), &TrackView::AboutToDeleteTrack, this, &TimelineWidget::TrackAboutToBeDeleted); + return v; +} + QByteArray TimelineWidget::SaveSplitterState() const { return view_splitter_->saveState(); diff --git a/app/widget/timelinewidget/timelinewidget.h b/app/widget/timelinewidget/timelinewidget.h index 99d3e7f1f..84d10e7fd 100644 --- a/app/widget/timelinewidget/timelinewidget.h +++ b/app/widget/timelinewidget/timelinewidget.h @@ -107,6 +107,10 @@ public: void DisableRecordingOverlay(); + void AddTentativeSubtitleTrack(); + + void ClearTentativeSubtitleTrack(); + /** * @brief Timelines should always be connected to sequences */ @@ -230,6 +234,7 @@ public: // Set to null subtitle_show_command_ = nullptr; + subtitle_tentative_track_ = nullptr; // Return command return c; @@ -298,6 +303,8 @@ private: bool PasteInternal(bool insert); + TimelineAndTrackView *AddTimelineAndTrackView(Qt::Alignment alignment); + QPoint drag_origin_; QRubberBand rubberband_; @@ -331,6 +338,7 @@ private: QSplitter* view_splitter_; MultiUndoCommand *subtitle_show_command_; + Track *subtitle_tentative_track_; QTimer *signal_block_change_timer_; @@ -420,6 +428,8 @@ private slots: void RenameSelectedBlocks(); + void TrackAboutToBeDeleted(Track *track); + }; } diff --git a/app/widget/timelinewidget/trackview/trackview.cpp b/app/widget/timelinewidget/trackview/trackview.cpp index fde1e8804..562c68d55 100644 --- a/app/widget/timelinewidget/trackview/trackview.cpp +++ b/app/widget/timelinewidget/trackview/trackview.cpp @@ -121,9 +121,13 @@ void TrackView::TrackHeightChanged(int index, int height) void TrackView::InsertTrack(Track *track) { + TrackViewItem *tvi = new TrackViewItem(track); + + connect(tvi, &TrackViewItem::AboutToDeleteTrack, this, &TrackView::AboutToDeleteTrack); + splitter_->Insert(track->Index(), track->GetTrackHeightInPixels(), - new TrackViewItem(track)); + tvi); } void TrackView::RemoveTrack(Track *track) diff --git a/app/widget/timelinewidget/trackview/trackview.h b/app/widget/timelinewidget/trackview/trackview.h index 89f131333..1498a526b 100644 --- a/app/widget/timelinewidget/trackview/trackview.h +++ b/app/widget/timelinewidget/trackview/trackview.h @@ -40,6 +40,9 @@ public: void ConnectTrackList(TrackList* list); void DisconnectTrackList(); +signals: + void AboutToDeleteTrack(Track *track); + protected: virtual void resizeEvent(QResizeEvent *e) override; diff --git a/app/widget/timelinewidget/trackview/trackviewitem.cpp b/app/widget/timelinewidget/trackview/trackviewitem.cpp index da84f8b27..6a5ba698e 100644 --- a/app/widget/timelinewidget/trackview/trackviewitem.cpp +++ b/app/widget/timelinewidget/trackview/trackviewitem.cpp @@ -145,6 +145,7 @@ void TrackViewItem::ShowContextMenu(const QPoint &p) void TrackViewItem::DeleteTrack() { + emit AboutToDeleteTrack(track_); Core::instance()->undo_stack()->push(new TimelineRemoveTrackCommand(track_)); } diff --git a/app/widget/timelinewidget/trackview/trackviewitem.h b/app/widget/timelinewidget/trackview/trackviewitem.h index d497c0241..7ec2eb750 100644 --- a/app/widget/timelinewidget/trackview/trackviewitem.h +++ b/app/widget/timelinewidget/trackview/trackviewitem.h @@ -38,6 +38,9 @@ public: TrackViewItem(Track* track, QWidget* parent = nullptr); +signals: + void AboutToDeleteTrack(Track *track); + private: QPushButton* CreateMSLButton(const QColor &checked_color) const;