From 33f8d7274aff1089aea6936f934c3a998371b6ed Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 19 Jul 2018 12:17:22 +0100 Subject: [PATCH] adding sequences can now be undone --- dialogs/newsequencedialog.cpp | 5 +++- panels/project.cpp | 31 ++++++++++++-------- panels/project.h | 4 ++- project/undo.cpp | 53 +++++++++++++++++++++++++++++++---- project/undo.h | 9 ++++++ ui/sourcetable.cpp | 4 ++- ui/timelinewidget.cpp | 9 +++--- 7 files changed, 92 insertions(+), 23 deletions(-) diff --git a/dialogs/newsequencedialog.cpp b/dialogs/newsequencedialog.cpp index 915b55305..80513d8a3 100644 --- a/dialogs/newsequencedialog.cpp +++ b/dialogs/newsequencedialog.cpp @@ -4,6 +4,7 @@ #include "panels/panels.h" #include "panels/project.h" #include "project/sequence.h" +#include "project/undo.h" #include #include @@ -61,7 +62,9 @@ void NewSequenceDialog::on_buttonBox_accepted() s->audio_frequency = ui->audio_frequency_combobox->currentData().toInt(); s->audio_layout = AV_CH_LAYOUT_STEREO; - panel_project->new_sequence(s, true, NULL); + TimelineAction* ta = new TimelineAction(); + panel_project->new_sequence(ta, s, true, NULL); + undo_stack.push(ta); } void NewSequenceDialog::on_comboBox_currentIndexChanged(int index) diff --git a/panels/project.cpp b/panels/project.cpp index 1f25e6a01..457fe4cdc 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -86,28 +86,40 @@ void Project::rename_media(QTreeWidgetItem* item, int column) { void Project::duplicate_selected() { QList items = ui->treeWidget->selectedItems(); + bool duped = false; + TimelineAction* ta = new TimelineAction(); for (int j=0;jcopy(), false, i->parent()); + new_sequence(ta, get_sequence_from_tree(i)->copy(), false, i->parent()); + duped = true; } } + if (duped) { + undo_stack.push(ta); + } else { + delete ta; + } } -void Project::new_sequence(Sequence *s, bool open, QTreeWidgetItem* parent) { +void Project::new_sequence(TimelineAction *ta, Sequence *s, bool open, QTreeWidgetItem* parent) { QTreeWidgetItem* item = new_item(); item->setText(0, s->name); set_sequence_of_tree(item, s); - if (parent == NULL) { - ui->treeWidget->addTopLevelItem(item); + if (ta != NULL) { + ta->new_sequence(item, parent); + if (open) ta->change_sequence(s); } else { - parent->addChild(item); + if (parent == NULL) { + ui->treeWidget->addTopLevelItem(item); + } else { + parent->addChild(item); + } + if (open) set_sequence(s); } project_changed = true; - - if (open) set_sequence(s); } QTreeWidgetItem* Project::import_file(QString file) { @@ -371,9 +383,6 @@ void Project::delete_media(QTreeWidgetItem* item) { break; case MEDIA_TYPE_SEQUENCE: Sequence* s = get_sequence_from_tree(item); - if (sequence == s) { - set_sequence(NULL); - } delete s; break; } @@ -632,7 +641,7 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) { } } - new_sequence(s, false, parent); + new_sequence(NULL, s, false, parent); } break; } diff --git a/panels/project.h b/panels/project.h index 07525755c..f845e5275 100644 --- a/panels/project.h +++ b/panels/project.h @@ -25,6 +25,8 @@ class QFile; #define LOAD_TYPE_VERSION 69 #define SAVE_SET_FOLDER_IDS 70 +class TimelineAction; + namespace Ui { class Project; } @@ -45,7 +47,7 @@ public: void clear(); QTreeWidgetItem* import_file(QString url); void import_dialog(); - void new_sequence(Sequence* s, bool open, QTreeWidgetItem* parent); + void new_sequence(TimelineAction* ta, Sequence* s, bool open, QTreeWidgetItem* parent); QString get_next_sequence_name(); void delete_media(QTreeWidgetItem* item); void delete_selected_media(); diff --git a/project/undo.cpp b/project/undo.cpp index 10e6c28da..5d5a950c9 100644 --- a/project/undo.cpp +++ b/project/undo.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "project/clip.h" #include "project/sequence.h" @@ -22,7 +23,7 @@ QUndoStack undo_stack; #define TA_ADD_CLIP_IN 7 #define TA_ADD_TRACK 8 -TimelineAction::TimelineAction() : done(false) {} +TimelineAction::TimelineAction() : done(false), change_seq(false) {} TimelineAction::~TimelineAction() { for (int i=0;iget_sequence_from_tree(new_sequence_items.at(i)); + delete new_sequence_items.at(i); + } + for (int i=0;idelete_media(media_to_add.at(i)); delete media_to_add.at(i); - }*/ + } } } @@ -53,6 +58,16 @@ void TimelineAction::offset_links(QVector& clips, int offset) { } } +void TimelineAction::change_sequence(Sequence* s) { + new_seq = s; + change_seq = true; +} + +void TimelineAction::new_sequence(QTreeWidgetItem *s, QTreeWidgetItem* parent) { + new_sequence_items.append(s); + new_sequence_parents.append(parent); +} + void TimelineAction::add_clips(Sequence* s, QVector& add) { offset_links(add, clips_to_add.size()); clips_to_add.append(add); @@ -156,6 +171,15 @@ void TimelineAction::undo() { } } + // add new sequences + for (int i=0;isource_table->takeTopLevelItem(panel_project->source_table->indexOfTopLevelItem(new_sequence_items.at(i))); + } else { + new_sequence_parents.at(i)->removeChild(new_sequence_items.at(i)); + } + } + // restore link references to deleted clips for (int i=0;iget_clip(removed_link_from.at(i))->linked.append(removed_link_to.at(i)); @@ -177,6 +201,10 @@ void TimelineAction::undo() { } } + if (change_seq) { + set_sequence(old_seq); + } + done = false; } @@ -190,6 +218,14 @@ void TimelineAction::redo() { deleted_media_parents.clear(); removed_link_from_sequence.clear(); + for (int i=0;isource_table->addTopLevelItem(new_sequence_items.at(i)); + } else { + new_sequence_parents.at(i)->addChild(new_sequence_items.at(i)); + } + } + for (int i=0;iget_type_from_tree(item) == MEDIA_TYPE_SEQUENCE) { - if (panel_project->get_sequence_from_tree(item) == sequence) { - set_sequence(NULL); + if (panel_project->get_sequence_from_tree(item) == sequence && !change_seq) { + old_seq = sequence; + new_seq = NULL; + change_seq = true; } } @@ -308,6 +346,11 @@ void TimelineAction::redo() { } } + if (change_seq) { + old_seq = sequence; + set_sequence(new_seq); + } + done = true; } diff --git a/project/undo.h b/project/undo.h index 86dcd8aee..0f3d91d10 100644 --- a/project/undo.h +++ b/project/undo.h @@ -15,6 +15,8 @@ class TimelineAction : public QUndoCommand { public: TimelineAction(); ~TimelineAction(); + void change_sequence(Sequence* s); + void new_sequence(QTreeWidgetItem* s, QTreeWidgetItem* parent); void add_clips(Sequence* s, QVector& add); void set_timeline_in(Sequence* s, int clip, long value); void increase_timeline_in(Sequence* s, int clip, long value); @@ -32,6 +34,13 @@ public: private: bool done; + bool change_seq; + Sequence* old_seq; + Sequence* new_seq; + + QVector new_sequence_items; + QVector new_sequence_parents; + QVector sequences; QVector actions; QVector clips; diff --git a/ui/sourcetable.cpp b/ui/sourcetable.cpp index 35a2e73d0..f4e456631 100644 --- a/ui/sourcetable.cpp +++ b/ui/sourcetable.cpp @@ -62,7 +62,9 @@ void SourceTable::mouseDoubleClickEvent(QMouseEvent* ) { } else if (selectedItems().count() == 1) { QTreeWidgetItem* item = selectedItems().at(0); if (panel_project->get_type_from_tree(item) == MEDIA_TYPE_SEQUENCE) { - set_sequence(panel_project->get_sequence_from_tree(item)); + TimelineAction* ta = new TimelineAction(); + ta->change_sequence(panel_project->get_sequence_from_tree(item)); + undo_stack.push(ta); } } } diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index b1503d98b..8b2736efa 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -173,8 +173,9 @@ void TimelineWidget::dropEvent(QDropEvent* event) { QVector added_clips; - if (sequence == NULL) { - Sequence* s = new Sequence(); + Sequence* s = sequence; + if (s == NULL) { + s = new Sequence(); // dumb hardcoded default values, should be settable somewhere s->name = panel_project->get_next_sequence_name(); @@ -184,7 +185,7 @@ void TimelineWidget::dropEvent(QDropEvent* event) { s->audio_frequency = predicted_audio_freq; s->audio_layout = predicted_audio_layout; - panel_project->new_sequence(s, true, NULL); + panel_project->new_sequence(ta, s, true, NULL); } else { // delete areas before adding QVector delete_areas; @@ -252,7 +253,7 @@ void TimelineWidget::dropEvent(QDropEvent* event) { } } - ta->add_clips(sequence, added_clips); + ta->add_clips(s, added_clips); panel_timeline->ghosts.clear(); panel_timeline->importing = false;