#include "undo.h" #include #include #include #include "project/clip.h" #include "project/sequence.h" #include "panels/panels.h" #include "panels/project.h" #include "panels/effectcontrols.h" #include "panels/viewer.h" #include "panels/timeline.h" #include "playback/playback.h" #include "ui/sourcetable.h" #include "project/effect.h" #include "io/media.h" #include "playback/cacher.h" #include "ui/labelslider.h" #include "ui/viewerwidget.h" #include "project/marker.h" #include "mainwindow.h" #include "debug.h" QUndoStack undo_stack; ComboAction::ComboAction() {} ComboAction::~ComboAction() { for (int i=0;i=0;i--) { commands.at(i)->undo(); } for (int i=0;iundo(); } } void ComboAction::redo() { for (int i=0;iredo(); } for (int i=0;iredo(); } } void ComboAction::append(QUndoCommand* u) { commands.append(u); } void ComboAction::appendPost(QUndoCommand* u) { post_commands.append(u); } MoveClipAction::MoveClipAction(Clip *c, long iin, long iout, long iclip_in, int itrack) : clip(c), old_in(c->timeline_in), old_out(c->timeline_out), old_clip_in(c->clip_in), old_track(c->track), new_in(iin), new_out(iout), new_clip_in(iclip_in), new_track(itrack), old_project_changed(mainWindow->isWindowModified()) {} void MoveClipAction::undo() { clip->timeline_in = old_in; clip->timeline_out = old_out; clip->clip_in = old_clip_in; clip->track = old_track; mainWindow->setWindowModified(old_project_changed); } void MoveClipAction::redo() { clip->timeline_in = new_in; clip->timeline_out = new_out; clip->clip_in = new_clip_in; clip->track = new_track; mainWindow->setWindowModified(true); } DeleteClipAction::DeleteClipAction(Sequence* s, int clip) : seq(s), index(clip), old_project_changed(mainWindow->isWindowModified()) {} DeleteClipAction::~DeleteClipAction() { if (ref != NULL) delete ref; } void DeleteClipAction::undo() { // restore ref to clip seq->clips[index] = ref; ref = NULL; // restore links to this clip for (int i=linkClipIndex.size()-1;i>=0;i--) { seq->clips.at(linkClipIndex.at(i))->linked.insert(linkLinkIndex.at(i), index); } mainWindow->setWindowModified(old_project_changed); } void DeleteClipAction::redo() { // remove ref to clip ref = seq->clips.at(index); if (ref->open) { close_clip(ref); } seq->clips[index] = NULL; // delete link to this clip linkClipIndex.clear(); linkLinkIndex.clear(); for (int i=0;iclips.size();i++) { Clip* c = seq->clips.at(i); if (c != NULL) { for (int j=0;jlinked.size();j++) { if (c->linked.at(j) == index) { linkClipIndex.append(i); linkLinkIndex.append(j); c->linked.removeAt(j); } } } } mainWindow->setWindowModified(true); } ChangeSequenceAction::ChangeSequenceAction(Sequence* s) : new_sequence(s) {} void ChangeSequenceAction::undo() { set_sequence(old_sequence); } void ChangeSequenceAction::redo() { old_sequence = sequence; set_sequence(new_sequence); } SetTimelineInOutCommand::SetTimelineInOutCommand(Sequence *s, bool enabled, long in, long out) : seq(s), new_enabled(enabled), new_in(in), new_out(out), old_project_changed(mainWindow->isWindowModified()) {} void SetTimelineInOutCommand::undo() { seq->using_workarea = old_enabled; seq->workarea_in = old_in; seq->workarea_out = old_out; // footage viewer functions if (seq->wrapper_sequence) { Media* m = static_cast(seq->clips.at(0)->media); m->using_inout = old_enabled; m->in = old_in; m->out = old_out; } mainWindow->setWindowModified(old_project_changed); } void SetTimelineInOutCommand::redo() { old_enabled = seq->using_workarea; old_in = seq->workarea_in; old_out = seq->workarea_out; seq->using_workarea = new_enabled; seq->workarea_in = new_in; seq->workarea_out = new_out; // footage viewer functions if (seq->wrapper_sequence) { Media* m = static_cast(seq->clips.at(0)->media); m->using_inout = new_enabled; m->in = new_in; m->out = new_out; } mainWindow->setWindowModified(true); } AddEffectCommand::AddEffectCommand(Clip* c, const EffectMeta *e) : clip(c), meta(e), ref(NULL), done(false), old_project_changed(mainWindow->isWindowModified()) {} AddEffectCommand::~AddEffectCommand() { if (!done && ref != NULL) delete ref; } void AddEffectCommand::undo() { clip->effects.removeLast(); done = false; mainWindow->setWindowModified(old_project_changed); } void AddEffectCommand::redo() { if (ref == NULL) { ref = create_effect(clip, meta); } clip->effects.append(ref); done = true; mainWindow->setWindowModified(true); } AddTransitionCommand::AddTransitionCommand(Clip* c, const EffectMeta *itransition, int itype, int ilength) : clip(c), transition(itransition), type(itype), length(ilength), old_project_changed(mainWindow->isWindowModified()) {} void AddTransitionCommand::undo() { if (type == TA_OPENING_TRANSITION) { delete clip->opening_transition; clip->opening_transition = NULL; } else { delete clip->closing_transition; clip->closing_transition = NULL; } mainWindow->setWindowModified(old_project_changed); } void AddTransitionCommand::redo() { if (type == TA_OPENING_TRANSITION) { clip->opening_transition = create_effect(clip, transition); if (length > 0) clip->opening_transition->length = length; } else { clip->closing_transition = create_effect(clip, transition); if (length > 0) clip->closing_transition->length = length; } mainWindow->setWindowModified(true); } ModifyTransitionCommand::ModifyTransitionCommand(Clip* c, int itype, long ilength) : clip(c), type(itype), new_length(ilength), old_project_changed(mainWindow->isWindowModified()) {} void ModifyTransitionCommand::undo() { if (type == TA_OPENING_TRANSITION) { clip->opening_transition->length = old_length; } else { clip->closing_transition->length = old_length; } mainWindow->setWindowModified(old_project_changed); } void ModifyTransitionCommand::redo() { if (type == TA_OPENING_TRANSITION) { old_length = clip->opening_transition->length; clip->opening_transition->length = new_length; } else { old_length = clip->closing_transition->length; clip->closing_transition->length = new_length; } mainWindow->setWindowModified(true); } DeleteTransitionCommand::DeleteTransitionCommand(Clip* c, int itype) : clip(c), type(itype), transition(NULL), old_project_changed(mainWindow->isWindowModified()) {} DeleteTransitionCommand::~DeleteTransitionCommand() { if (transition != NULL) delete transition; } void DeleteTransitionCommand::undo() { if (type == TA_OPENING_TRANSITION) { clip->opening_transition = transition; } else { clip->closing_transition = transition; } transition = NULL; mainWindow->setWindowModified(old_project_changed); } void DeleteTransitionCommand::redo() { if (type == TA_OPENING_TRANSITION) { transition = clip->opening_transition; clip->opening_transition = NULL; } else { transition = clip->closing_transition; clip->closing_transition = NULL; } mainWindow->setWindowModified(true); } NewSequenceCommand::NewSequenceCommand(QTreeWidgetItem *s, QTreeWidgetItem* iparent) : seq(s), parent(iparent), done(false), old_project_changed(mainWindow->isWindowModified()) {} NewSequenceCommand::~NewSequenceCommand() { if (!done) delete seq; } void NewSequenceCommand::undo() { if (parent == NULL) { panel_project->source_table->takeTopLevelItem(panel_project->source_table->indexOfTopLevelItem(seq)); } else { parent->removeChild(seq); } done = false; mainWindow->setWindowModified(old_project_changed); } void NewSequenceCommand::redo() { if (parent == NULL) { panel_project->source_table->addTopLevelItem(seq); } else { parent->addChild(seq); } done = true; mainWindow->setWindowModified(true); } AddMediaCommand::AddMediaCommand(QTreeWidgetItem* iitem, QTreeWidgetItem* iparent) : item(iitem), parent(iparent), done(false), old_project_changed(mainWindow->isWindowModified()) {} AddMediaCommand::~AddMediaCommand() { if (!done) { panel_project->delete_media(item); if (item->data(0, Qt::UserRole + 5) != 0) delete reinterpret_cast(item->data(0, Qt::UserRole + 5).value()); delete item; } } void AddMediaCommand::undo() { if (parent == NULL) { panel_project->source_table->takeTopLevelItem(panel_project->source_table->indexOfTopLevelItem(item)); } else { parent->removeChild(item); } done = false; mainWindow->setWindowModified(old_project_changed); } void AddMediaCommand::redo() { if (parent == NULL) { panel_project->source_table->addTopLevelItem(item); } else { parent->addChild(item); } /* Here we force the source_table to sort itself. * * For some reason, sometimes when you add items to the QTreeWidget, * (usually upon first import) they appear at the bottom, regardless * of where they should be placed alphabetically. Then when this * function is "undone", and it tries to remove this item from the * QTreeWidget, it immediately sorts and then removes THE WRONG ONE. * If this happens to be a sequence, the sequence data doesn't save * and is then lost forever (outside of autorecoveries). * * The following 2 lines seem to force the source_table to re-sort * correctly and therefore works around this problem. But holy shit. */ panel_project->source_table->setSortingEnabled(false); panel_project->source_table->setSortingEnabled(true); done = true; mainWindow->setWindowModified(true); } DeleteMediaCommand::DeleteMediaCommand(QTreeWidgetItem* i) : item(i), old_project_changed(mainWindow->isWindowModified()) {} DeleteMediaCommand::~DeleteMediaCommand() { if (done) { panel_project->delete_media(item); if (item->data(0, Qt::UserRole + 5) != 0) delete reinterpret_cast(item->data(0, Qt::UserRole + 5).value()); delete item; } } void DeleteMediaCommand::undo() { if (parent == NULL) { panel_project->source_table->addTopLevelItem(item); } else { parent->addChild(item); } mainWindow->setWindowModified(old_project_changed); done = false; } void DeleteMediaCommand::redo() { parent = item->parent(); if (parent == NULL) { panel_project->source_table->takeTopLevelItem(panel_project->source_table->indexOfTopLevelItem(item)); } else { parent->removeChild(item); } mainWindow->setWindowModified(true); done = true; } RippleCommand::RippleCommand(Sequence *s, long ipoint, long ilength) : seq(s), point(ipoint), length(ilength), old_project_changed(mainWindow->isWindowModified()) {} void RippleCommand::undo() { for (int i=0;itimeline_in -= length; c->timeline_out -= length; } mainWindow->setWindowModified(old_project_changed); } void RippleCommand::redo() { rippled.clear(); for (int j=0;jclips.size();j++) { Clip* c = seq->clips.at(j); bool found = false; for (int i=0;itimeline_in >= point) { c->timeline_in += length; c->timeline_out += length; rippled.append(c); } } } mainWindow->setWindowModified(true); } AddClipCommand::AddClipCommand(Sequence* s, QVector& add) : seq(s), clips(add), old_project_changed(mainWindow->isWindowModified()) {} AddClipCommand::~AddClipCommand() { for (int i=0;iclips.last(); panel_timeline->deselect_area(c->timeline_in, c->timeline_out, c->track); undone_clips.prepend(c); seq->clips.removeLast(); } mainWindow->setWindowModified(old_project_changed); } void AddClipCommand::redo() { if (undone_clips.size() > 0) { for (int i=0;iclips.append(undone_clips.at(i)); } undone_clips.clear(); } else { int linkOffset = seq->clips.size(); for (int i=0;icopy(seq); copy->linked.resize(original->linked.size()); for (int j=0;jlinked.size();j++) { copy->linked[j] = original->linked.at(j) + linkOffset; } seq->clips.append(copy); } } mainWindow->setWindowModified(true); } /* #define TA_ADD_EFFECT 9 #define TA_ADD_TRANSITION 10 #define TA_MODIFY_TRANSITION 11 #define TA_DELETE_TRANSITION 12 TimelineAction::TimelineAction() : done(false), change_seq(false), ripple_enabled(false), change_in_out(false), old_project_changed(mainWindow->isWindowModified()) {} TimelineAction::~TimelineAction() { for (int i=0;idelete_media(deleted_media.at(i)); delete deleted_media.at(i); } } else { for (int i=0;idelete_media(media_to_add.at(i)); delete media_to_add.at(i); } } } void TimelineAction::offset_links(QVector& clips, int offset) { for (int i=0;ilinked.size();j++) { c->linked[j] += 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); for (int i=0;iget_clip(clip)->timeline_in, value); } void TimelineAction::set_timeline_out(Sequence* s, int clip, long value) { new_action(s, TA_OUT, clip, TA_NO_TRANSITION, s->get_clip(clip)->timeline_out, value); } void TimelineAction::set_clip_in(Sequence* s, int clip, long value) { new_action(s, TA_CLIP_IN, clip, TA_NO_TRANSITION, s->get_clip(clip)->clip_in, value); } void TimelineAction::set_track(Sequence* s, int clip, int value) { new_action(s, TA_TRACK, clip, TA_NO_TRANSITION, s->get_clip(clip)->track, value); } void TimelineAction::increase_timeline_in(Sequence* s, int clip, long value) { new_action(s, TA_ADD_IN, clip, TA_NO_TRANSITION, 0, value); } void TimelineAction::increase_timeline_out(Sequence* s, int clip, long value) { new_action(s, TA_ADD_OUT, clip, TA_NO_TRANSITION, 0, value); } void TimelineAction::increase_clip_in(Sequence* s, int clip, long value) { new_action(s, TA_ADD_CLIP_IN, clip, TA_NO_TRANSITION, 0, value); } void TimelineAction::increase_track(Sequence* s, int clip, int value) { new_action(s, TA_ADD_TRACK, clip, TA_NO_TRANSITION, 0, value); } void TimelineAction::delete_clip(Sequence* s, int clip) { new_action(s, TA_DELETE, clip, TA_NO_TRANSITION, 0, 0); } void TimelineAction::add_media(QTreeWidgetItem* item, QTreeWidgetItem *parent) { media_to_add.append(item); media_to_add_parents.append(parent); } void TimelineAction::delete_media(QTreeWidgetItem* item) { deleted_media.append(item); } void TimelineAction::ripple(Sequence* s, long point, long length) { QVector i; ripple(s, point, length, i); } void TimelineAction::add_effect(Sequence* s, int clip, int effect) { new_action(s, TA_ADD_EFFECT, clip, TA_NO_TRANSITION, 0, effect); } void TimelineAction::add_transition(Sequence* s, int clip, int transition, int type) { new_action(s, TA_ADD_TRANSITION, clip, type, 0, transition); } void TimelineAction::modify_transition(Sequence* s, int clip, int type, long length) { new_action(s, TA_MODIFY_TRANSITION, clip, type, 0, length); } void TimelineAction::delete_transition(Sequence* s, int clip, int type) { new_action(s, TA_DELETE_TRANSITION, clip, type, 0, 0); } void TimelineAction::set_in_out(Sequence* s, bool enabled, long in, long out) { change_in_out = true; change_in_out_sequence = s; old_in_out_enabled = s->using_workarea; old_sequence_in = s->workarea_in; old_sequence_out = s->workarea_out; new_in_out_enabled = enabled; new_sequence_in = in; new_sequence_out = out; } void TimelineAction::ripple(Sequence* s, long point, long length, QVector& ignore) { ripple_enabled = true; ripple_point = point; ripple_length = length; ripple_sequence = s; ripple_ignores = ignore; } void TimelineAction::undo() { // re-add deleted media for (int i=0;isource_table->addTopLevelItem(item); } else { parent->addChild(item); } } // de-ripple clips if (ripple_enabled) { for (int i=0;iget_clip(rippled_clips.at(i)); c->timeline_in -= ripple_length; c->timeline_out -= ripple_length; } } for (int i=actions.size()-1;i>=0;i--) { switch (actions.at(i)) { case TA_IN: sequences.at(i)->get_clip(clips.at(i))->timeline_in = old_values.at(i); break; case TA_OUT: sequences.at(i)->get_clip(clips.at(i))->timeline_out = old_values.at(i); break; case TA_CLIP_IN: sequences.at(i)->get_clip(clips.at(i))->clip_in = old_values.at(i); break; case TA_TRACK: sequences.at(i)->get_clip(clips.at(i))->track = old_values.at(i); break; case TA_DELETE: sequences.at(i)->replace_clip(clips.at(i), deleted_clips.at(new_values.at(i))); break; case TA_ADD_IN: sequences.at(i)->get_clip(clips.at(i))->timeline_in -= new_values.at(i); break; case TA_ADD_OUT: sequences.at(i)->get_clip(clips.at(i))->timeline_out -= new_values.at(i); break; case TA_ADD_CLIP_IN: sequences.at(i)->get_clip(clips.at(i))->clip_in -= new_values.at(i); break; case TA_ADD_TRACK: sequences.at(i)->get_clip(clips.at(i))->track -= new_values.at(i); break; case TA_ADD_EFFECT: { Clip* c = sequences.at(i)->get_clip(clips.at(i)); Effect* effect = c->effects.at(old_values.at(i)); c->effects.removeAt(old_values.at(i)); delete effect; } break; case TA_ADD_TRANSITION: { Clip* c = sequences.at(i)->get_clip(clips.at(i)); if (transition_types.at(i) == TA_OPENING_TRANSITION) { delete c->opening_transition; c->opening_transition = NULL; } else { delete c->closing_transition; c->closing_transition = NULL; } } break; case TA_MODIFY_TRANSITION: { Clip* c = sequences.at(i)->get_clip(clips.at(i)); if (transition_types.at(i) == TA_OPENING_TRANSITION) { c->opening_transition->length = old_values.at(i); } else { c->closing_transition->length = old_values.at(i); } } break; case TA_DELETE_TRANSITION: { Clip* c = sequences.at(i)->get_clip(clips.at(i)); if (transition_types.at(i) == TA_OPENING_TRANSITION) { c->opening_transition = create_transition(new_values.at(i), c); c->opening_transition->length = old_values.at(i); } else { c->closing_transition = create_transition(new_values.at(i), c); c->closing_transition->length = old_values.at(i); } } break; } } // remove added 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)); } // delete added clips int delete_count = 0; for (int i=0;idestroy_clip(added_indexes.at(i)-delete_count, true); delete_count++; } // remove any added media for (int i=0;isource_table->takeTopLevelItem(panel_project->source_table->indexOfTopLevelItem(media_to_add.at(i))); } else { media_to_add_parents.at(i)->removeChild(media_to_add.at(i)); } } // un-change workarea if (change_in_out) { change_in_out_sequence->using_workarea = old_in_out_enabled; change_in_out_sequence->workarea_in = old_sequence_in; change_in_out_sequence->workarea_out = old_sequence_out; } // un-change current active sequence if (change_seq) { set_sequence(old_seq); } mainWindow->setWindowModified(old_project_changed); done = false; } void TimelineAction::redo() { removed_link_from.clear(); removed_link_to.clear(); deleted_clips.clear(); deleted_clips_indices.clear(); deleted_clip_sequences.clear(); added_indexes.clear(); deleted_media_parents.clear(); removed_link_from_sequence.clear(); rippled_clips.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)); } } // add any new clips if (clips_to_add.size() > 0) { QVector copies; for (int i=0;icopy(sequence_to_add_clips_to.at(i)); copy->linked.resize(original->linked.size()); for (int j=0;jlinked.size();j++) { copy->linked[j] = original->linked.at(j) + sequence_to_add_clips_to.at(i)->clip_count(); } copies.append(copy); } for (int i=0;iadd_clip(copies.at(i))); } } for (int i=0;iget_clip(clips.at(i))->timeline_in = new_values.at(i); } break; case TA_OUT: { sequences.at(i)->get_clip(clips.at(i))->timeline_out = new_values.at(i); } break; case TA_CLIP_IN: { sequences.at(i)->get_clip(clips.at(i))->clip_in = new_values.at(i); } break; case TA_TRACK: { sequences.at(i)->get_clip(clips.at(i))->track = new_values.at(i); } break; case TA_DELETE: { new_values[i] = deleted_clips.size(); deleted_clips.append(sequences.at(i)->get_clip(clips.at(i))); deleted_clips_indices.append(clips.at(i)); deleted_clip_sequences.append(sequences.at(i)); sequences.at(i)->replace_clip(clips.at(i), NULL); } break; case TA_ADD_IN: { sequences.at(i)->get_clip(clips.at(i))->timeline_in += new_values.at(i); } break; case TA_ADD_OUT: { sequences.at(i)->get_clip(clips.at(i))->timeline_out += new_values.at(i); } break; case TA_ADD_CLIP_IN: { sequences.at(i)->get_clip(clips.at(i))->clip_in += new_values.at(i); } break; case TA_ADD_TRACK: { sequences.at(i)->get_clip(clips.at(i))->track += new_values.at(i); } break; case TA_ADD_EFFECT: { Clip* c = sequences.at(i)->get_clip(clips.at(i)); old_values[i] = c->effects.size(); Effect* e = create_effect(new_values.at(i), c); c->effects.append(e); } break; case TA_ADD_TRANSITION: { Clip* c = sequences.at(i)->get_clip(clips.at(i)); if (transition_types.at(i) == TA_OPENING_TRANSITION) { c->opening_transition = create_transition(new_values.at(i), c); } else { c->closing_transition = create_transition(new_values.at(i), c); } } break; case TA_MODIFY_TRANSITION: { Clip* c = sequences.at(i)->get_clip(clips.at(i)); if (transition_types.at(i) == TA_OPENING_TRANSITION) { old_values[i] = c->opening_transition->length; c->opening_transition->length = new_values.at(i); } else { old_values[i] = c->closing_transition->length; c->closing_transition->length = new_values.at(i); } } break; case TA_DELETE_TRANSITION: { Clip* c = sequences.at(i)->get_clip(clips.at(i)); if (transition_types.at(i) == TA_OPENING_TRANSITION) { new_values[i] = c->opening_transition->id; old_values[i] = c->opening_transition->length; delete c->opening_transition; c->opening_transition = NULL; } else { new_values[i] = c->closing_transition->id; old_values[i] = c->closing_transition->length; delete c->closing_transition; c->closing_transition = NULL; } } break; } } // remove any potential link references from deleted clips for (int i=0;iclip_count();j++) { Clip* c = s->get_clip(j); if (c != NULL) { for (int k=0;klinked.size();k++) { if (c->linked.at(k) == deleted_clips_indices.at(i)) { removed_link_from_sequence.append(s); removed_link_from.append(j); removed_link_to.append(deleted_clips_indices.at(i)); c->linked.removeAt(k); break; } } } } } // ripple clips - moves all clips after a certain ripple_point by ripple_length if (ripple_enabled) { for (int j=0;jclip_count();j++) { bool found = false; for (int i=0;iget_clip(j); if (c != NULL && c->timeline_in >= ripple_point) { c->timeline_in += ripple_length; c->timeline_out += ripple_length; rippled_clips.append(j); } } } } // delete media for (int i=0;iparent()); // if we're deleting the open sequence, close it if (get_type_from_tree(item) == MEDIA_TYPE_SEQUENCE && get_sequence_from_tree(item) == sequence && !change_seq) { old_seq = sequence; new_seq = NULL; change_seq = true; } if (item->parent() == NULL) { panel_project->source_table->takeTopLevelItem(panel_project->source_table->indexOfTopLevelItem(item)); } else { item->parent()->removeChild(item); } } // add any new media for (int i=0;isource_table->addTopLevelItem(media_to_add.at(i)); } else { media_to_add_parents.at(i)->addChild(media_to_add.at(i)); } } // change sequence workarea if (change_in_out) { change_in_out_sequence->using_workarea = new_in_out_enabled; change_in_out_sequence->workarea_in = new_sequence_in; change_in_out_sequence->workarea_out = new_sequence_out; } // change current sequence if (change_seq) { old_seq = sequence; set_sequence(new_seq); } mainWindow->setWindowModified(true); done = true; }*/ LinkCommand::LinkCommand() : link(true), old_project_changed(mainWindow->isWindowModified()) {} void LinkCommand::undo() { for (int i=0;iclips.at(clips.at(i)); if (link) { c->linked.clear(); } else { c->linked = old_links.at(i); } } mainWindow->setWindowModified(old_project_changed); } void LinkCommand::redo() { old_links.clear(); for (int i=0;iclips.at(clips.at(i)); if (link) { for (int j=0;jlinked.append(clips.at(j)); } } } else { old_links.append(c->linked); c->linked.clear(); } } mainWindow->setWindowModified(true); } CheckboxCommand::CheckboxCommand(QCheckBox* b) : box(b), checked(box->isChecked()), done(true), old_project_changed(mainWindow->isWindowModified()) {} CheckboxCommand::~CheckboxCommand() {} void CheckboxCommand::undo() { box->setChecked(!checked); done = false; mainWindow->setWindowModified(old_project_changed); } void CheckboxCommand::redo() { if (!done) { box->setChecked(checked); } mainWindow->setWindowModified(true); } ReplaceMediaCommand::ReplaceMediaCommand(QTreeWidgetItem* i, QString s) : item(i), new_filename(s), old_project_changed(mainWindow->isWindowModified()) { media = get_footage_from_tree(item); old_filename = media->url; } void ReplaceMediaCommand::replace(QString& filename) { // close any clips currently using this media QVector all_sequences = panel_project->list_all_project_sequences(); for (int i=0;iclips.size();j++) { Clip* c = s->clips.at(j); if (c != NULL && c->media == media && c->open) { close_clip(c); if (c->media_type == MEDIA_TYPE_FOOTAGE) c->cacher->wait(); c->replaced = true; } } } // replace media QStringList files; files.append(filename); panel_project->process_file_list(false, files, NULL, item); } void ReplaceMediaCommand::undo() { replace(old_filename); mainWindow->setWindowModified(old_project_changed); } void ReplaceMediaCommand::redo() { replace(new_filename); mainWindow->setWindowModified(true); } ReplaceClipMediaCommand::ReplaceClipMediaCommand(void *a, void *b, int c, int d, bool e) : old_media(a), new_media(b), old_type(c), new_type(d), preserve_clip_ins(e), old_project_changed(mainWindow->isWindowModified()) {} void ReplaceClipMediaCommand::replace(bool undo) { if (!undo) { old_clip_ins.clear(); } for (int i=0;iopen) { close_clip(c); if (c->media_type == MEDIA_TYPE_FOOTAGE) c->cacher->wait(); } if (undo) { if (!preserve_clip_ins) { c->clip_in = old_clip_ins.at(i); } c->media = old_media; c->media_type = old_type; } else { if (!preserve_clip_ins) { old_clip_ins.append(c->clip_in); c->clip_in = 0; } c->media = new_media; c->media_type = new_type; } c->replaced = true; c->refresh(); } } void ReplaceClipMediaCommand::undo() { replace(true); mainWindow->setWindowModified(old_project_changed); } void ReplaceClipMediaCommand::redo() { replace(false); mainWindow->setWindowModified(true); } EffectDeleteCommand::EffectDeleteCommand() : done(false), old_project_changed(mainWindow->isWindowModified()) {} EffectDeleteCommand::~EffectDeleteCommand() { if (done) { for (int i=0;ieffects.insert(fx.at(i), deleted_objects.at(i)); } panel_effect_controls->reload_clips(); done = false; mainWindow->setWindowModified(old_project_changed); } void EffectDeleteCommand::redo() { deleted_objects.clear(); for (int i=0;ieffects.at(fx_id)); c->effects.removeAt(fx_id); } panel_effect_controls->reload_clips(); done = true; mainWindow->setWindowModified(true); } MediaMove::MediaMove(SourceTable *s) : table(s), old_project_changed(mainWindow->isWindowModified()) {} void MediaMove::undo() { for (int i=0;itakeTopLevelItem(table->indexOfTopLevelItem(items.at(i))); } else { to->removeChild(items.at(i)); } } for (int i=0;iaddTopLevelItem(items.at(i)); } else { froms.at(i)->addChild(items.at(i)); } } mainWindow->setWindowModified(old_project_changed); } void MediaMove::redo() { froms.resize(items.size()); for (int i=0;iparent(); froms[i] = parent; if (parent == NULL) { table->takeTopLevelItem(table->indexOfTopLevelItem(items.at(i))); } else { parent->removeChild(items.at(i)); } if (to == NULL) { table->addTopLevelItem(items.at(i)); } else { to->addChild(items.at(i)); } } for (int i=0;iaddTopLevelItem(items.at(i)); } else { to->addChild(items.at(i)); } } mainWindow->setWindowModified(true); } MediaRename::MediaRename() : done(true), old_project_changed(mainWindow->isWindowModified()) {} void MediaRename::undo() { item->setText(0, from); done = false; mainWindow->setWindowModified(old_project_changed); } void MediaRename::redo() { if (!done) { item->setText(0, to); } mainWindow->setWindowModified(true); } KeyframeMove::KeyframeMove() : old_project_changed(mainWindow->isWindowModified()) {} void KeyframeMove::undo() { for (int i=0;ikeyframe_times[keyframes.at(i)] -= movement; } mainWindow->setWindowModified(old_project_changed); } void KeyframeMove::redo() { for (int i=0;ikeyframe_times[keyframes.at(i)] += movement; } mainWindow->setWindowModified(true); } KeyframeDelete::KeyframeDelete() : disable_keyframes_on_row(NULL), old_project_changed(mainWindow->isWindowModified()), sorted(false) {} void KeyframeDelete::undo() { if (disable_keyframes_on_row != NULL) disable_keyframes_on_row->setKeyframing(true); int data_index = deleted_keyframe_data.size()-1; for (int i=rows.size()-1;i>=0;i--) { EffectRow* row = rows.at(i); int keyframe_index = keyframes.at(i); row->keyframe_times.insert(keyframe_index, deleted_keyframe_times.at(i)); row->keyframe_types.insert(keyframe_index, deleted_keyframe_types.at(i)); for (int j=row->fieldCount()-1;j>=0;j--) { row->field(j)->keyframe_data.insert(keyframe_index, deleted_keyframe_data.at(data_index)); data_index--; } } mainWindow->setWindowModified(old_project_changed); } void KeyframeDelete::redo() { if (!sorted) { deleted_keyframe_times.resize(rows.size()); deleted_keyframe_types.resize(rows.size()); deleted_keyframe_data.clear(); } for (int i=0;ikeyframe_times.at(keyframe_index)); deleted_keyframe_types[i] = (row->keyframe_types.at(keyframe_index)); } row->keyframe_times.removeAt(keyframe_index); row->keyframe_types.removeAt(keyframe_index); for (int j=0;jfieldCount();j++) { if (!sorted) deleted_keyframe_data.append(row->field(j)->keyframe_data.at(keyframe_index)); row->field(j)->keyframe_data.removeAt(keyframe_index); } // correct following indices if (!sorted) { for (int j=i+1;j keyframe_index) { keyframes[j]--; } } } } if (disable_keyframes_on_row != NULL) disable_keyframes_on_row->setKeyframing(false); mainWindow->setWindowModified(true); sorted = true; } KeyframeSet::KeyframeSet(EffectRow* r, int i, long t, bool justMadeKeyframe) : old_project_changed(mainWindow->isWindowModified()), row(r), index(i), time(t), just_made_keyframe(justMadeKeyframe), done(true) { enable_keyframes = !row->isKeyframing(); if (index != -1) old_values.resize(row->fieldCount()); new_values.resize(row->fieldCount()); for (int i=0;ifieldCount();i++) { EffectField* field = row->field(i); if (index != -1) { if (field->type == EFFECT_FIELD_DOUBLE) { old_values[i] = static_cast(field->ui_element)->get_drag_start_value(); } else { old_values[i] = field->keyframe_data.at(index); } } new_values[i] = field->get_current_data(); } } void KeyframeSet::undo() { if (enable_keyframes) row->setKeyframing(false); bool append = (index == -1 || just_made_keyframe); if (append) { row->keyframe_times.removeLast(); row->keyframe_types.removeLast(); } for (int i=0;ifieldCount();i++) { if (append) { row->field(i)->keyframe_data.removeLast(); } else { row->field(i)->keyframe_data[index] = old_values.at(i); } } mainWindow->setWindowModified(old_project_changed); done = false; } void KeyframeSet::redo() { bool append = (index == -1 || (just_made_keyframe && !done)); if (append) { row->keyframe_times.append(time); row->keyframe_types.append((row->keyframe_types.size() > 0) ? row->keyframe_types.last() : EFFECT_KEYFRAME_LINEAR); } for (int i=0;ifieldCount();i++) { if (append) { row->field(i)->keyframe_data.append(new_values.at(i)); } else { row->field(i)->keyframe_data[index] = new_values.at(i); } } row->setKeyframing(true); mainWindow->setWindowModified(true); done = true; } EffectFieldUndo::EffectFieldUndo(EffectField* f) : field(f), done(true), old_project_changed(mainWindow->isWindowModified()) { old_val = field->get_previous_data(); new_val = field->get_current_data(); } void EffectFieldUndo::undo() { field->set_current_data(old_val); done = false; mainWindow->setWindowModified(old_project_changed); } void EffectFieldUndo::redo() { if (!done) { field->set_current_data(new_val); } mainWindow->setWindowModified(true); } SetAutoscaleAction::SetAutoscaleAction() : old_project_changed(mainWindow->isWindowModified()) {} void SetAutoscaleAction::undo() { for (int i=0;iautoscale = !clips.at(i)->autoscale; } panel_sequence_viewer->viewer_widget->update(); mainWindow->setWindowModified(old_project_changed); } void SetAutoscaleAction::redo() { for (int i=0;iautoscale = !clips.at(i)->autoscale; } panel_sequence_viewer->viewer_widget->update(); mainWindow->setWindowModified(true); } AddMarkerAction::AddMarkerAction(Sequence* s, long t, QString n) : seq(s), time(t), name(n), old_project_changed(mainWindow->isWindowModified()) {} void AddMarkerAction::undo() { if (index == -1) { seq->markers.removeLast(); } else { seq->markers[index].name = old_name; } mainWindow->setWindowModified(old_project_changed); } void AddMarkerAction::redo() { index = -1; for (int i=0;imarkers.size();i++) { if (seq->markers.at(i).frame == time) { index = i; break; } } if (index == -1) { Marker m; m.frame = time; seq->markers.append(m); } else { old_name = seq->markers.at(index).name; seq->markers[index].name = name; } mainWindow->setWindowModified(true); } MoveMarkerAction::MoveMarkerAction(Marker* m, long o, long n) : marker(m), old_time(o), new_time(n), old_project_changed(mainWindow->isWindowModified()) {} void MoveMarkerAction::undo() { marker->frame = old_time; mainWindow->setWindowModified(old_project_changed); } void MoveMarkerAction::redo() { marker->frame = new_time; mainWindow->setWindowModified(true); } DeleteMarkerAction::DeleteMarkerAction(Sequence* s) : seq(s), sorted(false), old_project_changed(mainWindow->isWindowModified()) {} void DeleteMarkerAction::undo() { for (int i=markers.size()-1;i>=0;i--) { seq->markers.insert(markers.at(i), copies.at(i)); } mainWindow->setWindowModified(old_project_changed); } void DeleteMarkerAction::redo() { for (int i=0;imarkers.at(markers.at(i))); for (int j=i+1;j markers.at(i)) { markers[j]--; } } } seq->markers.removeAt(markers.at(i)); } sorted = true; mainWindow->setWindowModified(true); } SetSpeedAction::SetSpeedAction(Clip* c, double speed) : clip(c), old_speed(c->speed), new_speed(speed), old_project_changed(mainWindow->isWindowModified()) {} void SetSpeedAction::undo() { clip->speed = old_speed; clip->recalculateMaxLength(); mainWindow->setWindowModified(old_project_changed); } void SetSpeedAction::redo() { clip->speed = new_speed; clip->recalculateMaxLength(); mainWindow->setWindowModified(true); } SetBool::SetBool(bool* b, bool setting) : boolean(b), old_setting(*b), new_setting(setting), old_project_changed(mainWindow->isWindowModified()) {} void SetBool::undo() { *boolean = old_setting; mainWindow->setWindowModified(old_project_changed); } void SetBool::redo() { *boolean = new_setting; mainWindow->setWindowModified(true); } SetSelectionsCommand::SetSelectionsCommand(Sequence* s) : seq(s), done(true), old_project_changed(mainWindow->isWindowModified()) {} void SetSelectionsCommand::undo() { seq->selections = old_data; done = false; mainWindow->setWindowModified(old_project_changed); } void SetSelectionsCommand::redo() { if (!done) { seq->selections = new_data; done = true; } mainWindow->setWindowModified(true); } SetEnableCommand::SetEnableCommand(Clip* c, bool enable) : clip(c), old_val(c->enabled), new_val(enable), old_project_changed(mainWindow->isWindowModified()) {} void SetEnableCommand::undo() { clip->enabled = old_val; mainWindow->setWindowModified(old_project_changed); } void SetEnableCommand::redo() { clip->enabled = new_val; mainWindow->setWindowModified(true); } EditSequenceCommand::EditSequenceCommand(QTreeWidgetItem* i, Sequence *s) : item(i), seq(s), old_project_changed(mainWindow->isWindowModified()), old_name(s->name), old_width(s->width), old_height(s->height), old_frame_rate(s->frame_rate), old_audio_frequency(s->audio_frequency), old_audio_layout(s->audio_layout) {} void EditSequenceCommand::undo() { seq->name = old_name; seq->width = old_width; seq->height = old_height; seq->frame_rate = old_frame_rate; seq->audio_frequency = old_audio_frequency; seq->audio_layout = old_audio_layout; update(); mainWindow->setWindowModified(old_project_changed); } void EditSequenceCommand::redo() { seq->name = name; seq->width = width; seq->height = height; seq->frame_rate = frame_rate; seq->audio_frequency = audio_frequency; seq->audio_layout = audio_layout; update(); mainWindow->setWindowModified(true); } void EditSequenceCommand::update() { // update name item->setText(0, seq->name); // update tooltip set_sequence_of_tree(item, seq); for (int i=0;iclips.size();i++) { // TODO shift in/out/clipin points to match new frame rate // BUT ALSO copy/paste must need a similar routine, no? // See if one exists or if you have to make one, make it // re-usable seq->clips.at(i)->refresh(); } if (sequence == seq) { set_sequence(seq); } } SetInt::SetInt(int* pointer, int new_value) : p(pointer), oldval(*pointer), newval(new_value), old_project_changed(mainWindow->isWindowModified()) {} void SetInt::undo() { *p = oldval; mainWindow->setWindowModified(old_project_changed); } void SetInt::redo() { *p = newval; mainWindow->setWindowModified(true); } SetString::SetString(QString* pointer, QString new_value) : p(pointer), oldval(*pointer), newval(new_value), old_project_changed(mainWindow->isWindowModified()) {} void SetString::undo() { *p = oldval; mainWindow->setWindowModified(old_project_changed); } void SetString::redo() { *p = newval; mainWindow->setWindowModified(true); } void CloseAllClipsCommand::undo() { redo(); } void CloseAllClipsCommand::redo() { closeActiveClips(sequence, true); } UpdateFootageTooltip::UpdateFootageTooltip(QTreeWidgetItem *i, Media *m) : item(i), media(m) {} void UpdateFootageTooltip::undo() { redo(); } void UpdateFootageTooltip::redo() { update_footage_tooltip(item, media); } MoveEffectCommand::MoveEffectCommand() : old_project_changed(mainWindow->isWindowModified()) {} void MoveEffectCommand::undo() { clip->effects.move(to, from); mainWindow->setWindowModified(old_project_changed); } void MoveEffectCommand::redo() { clip->effects.move(from, to); mainWindow->setWindowModified(true); } RemoveClipsFromClipboard::RemoveClipsFromClipboard(int index) : pos(index), old_project_changed(mainWindow->isWindowModified()), done(false) {} RemoveClipsFromClipboard::~RemoveClipsFromClipboard() { if (done) { delete clip; } } void RemoveClipsFromClipboard::undo() { panel_timeline->clip_clipboard.insert(pos, clip); done = false; } void RemoveClipsFromClipboard::redo() { clip = panel_timeline->clip_clipboard.at(pos); panel_timeline->clip_clipboard.removeAt(pos); done = true; } RenameClipCommand::RenameClipCommand() : old_project_changed(mainWindow->isWindowModified()) {} void RenameClipCommand::undo() { for (int i=0;iname = old_names.at(i); } } void RenameClipCommand::redo() { old_names.resize(clips.size()); for (int i=0;iname; clips.at(i)->name = new_name; } }