timeline: handle users deleting tentative subtitle track

Fixes potential crash if users try to do this
This commit is contained in:
itsmattkc
2022-05-11 13:47:12 -07:00
parent 78d5314c0a
commit f17c119c29
6 changed files with 85 additions and 31 deletions
+63 -30
View File
@@ -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<int> 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;i<Track::kCount;i++) {
@@ -1116,32 +1155,9 @@ void TimelineWidget::AddableObjectChanged()
{
// Special cast for subtitle adding - ensure section is visible
if (Core::instance()->tool() == Tool::kAdd && Core::instance()->GetSelectedAddableObject() == Tool::kAddableSubtitle) {
if (!subtitle_show_command_) {
// Determine if we need to do anything
QList<int> 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();
@@ -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);
};
}
@@ -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)
@@ -40,6 +40,9 @@ public:
void ConnectTrackList(TrackList* list);
void DisconnectTrackList();
signals:
void AboutToDeleteTrack(Track *track);
protected:
virtual void resizeEvent(QResizeEvent *e) override;
@@ -145,6 +145,7 @@ void TrackViewItem::ShowContextMenu(const QPoint &p)
void TrackViewItem::DeleteTrack()
{
emit AboutToDeleteTrack(track_);
Core::instance()->undo_stack()->push(new TimelineRemoveTrackCommand(track_));
}
@@ -38,6 +38,9 @@ public:
TrackViewItem(Track* track,
QWidget* parent = nullptr);
signals:
void AboutToDeleteTrack(Track *track);
private:
QPushButton* CreateMSLButton(const QColor &checked_color) const;