many project window enhancements

This commit is contained in:
itsmattkc
2018-07-15 12:31:10 +01:00
parent fdc9506eb3
commit a614803b6c
11 changed files with 417 additions and 164 deletions
+11 -2
View File
@@ -353,6 +353,7 @@ void MainWindow::on_action_Open_Project_triggered()
if (!fn.isEmpty() && can_close_project()) {
project_url = fn;
panel_project->load_project();
undo_stack.clear();
}
}
@@ -362,6 +363,7 @@ void MainWindow::on_actionProject_triggered()
project_url.clear();
project_changed = false;
panel_project->new_project();
undo_stack.clear();
}
}
@@ -595,8 +597,15 @@ void MainWindow::fileMenu_About_To_Be_Shown() {
}
void MainWindow::load_recent_project() {
if (can_close_project()) {
project_url = recent_projects.at(static_cast<QAction*>(sender())->data().toInt());
int index = static_cast<QAction*>(sender())->data().toInt();
QString recent_url = recent_projects.at(index);
if (!QFile::exists(recent_url)) {
if (QMessageBox::question(this, "Missing recent project", "The project '" + recent_url + "' no longer exists. Would you like to remove it from the recent projects list?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
recent_projects.removeAt(index);
panel_project->save_recent_projects();
}
} else if (can_close_project()) {
project_url = recent_url;
panel_project->load_project();
}
}
+145 -50
View File
@@ -12,6 +12,7 @@
#include "project/effect.h"
#include "effects/transition.h"
#include "io/previewgenerator.h"
#include "project/undo.h"
#include "mainwindow.h"
#include <QFileDialog>
@@ -203,46 +204,100 @@ QTreeWidgetItem* Project::new_folder() {
return item;
}
void Project::get_media_from_table(QList<QTreeWidgetItem*> items, QList<QTreeWidgetItem*>& list, int search_type) {
for (int i=0;i<items.size();i++) {
QTreeWidgetItem* item = items.at(i);
int type = get_type_from_tree(item);
if (type == MEDIA_TYPE_FOLDER) {
QList<QTreeWidgetItem*> children;
for (int j=0;j<item->childCount();j++) {
children.append(item->child(j));
}
get_media_from_table(children, list, search_type);
} else if (search_type == type) {
list.append(item);
}
}
}
void Project::delete_selected_media() {
TimelineAction* ta = new TimelineAction();
QList<QTreeWidgetItem*> items = ui->treeWidget->selectedItems();
bool remove = true;
bool redraw = false;
// check if media is in use
for (int i=0;i<items.size();i++) {
QTreeWidgetItem* item = items.at(i);
Media* m = get_media_from_tree(item);
if (get_type_from_tree(item) == MEDIA_TYPE_FOOTAGE && sequence != NULL) {
for (int j=0;j<sequence->clip_count();j++) {
Clip* c = sequence->get_clip(j);
if (c != NULL && c->media == m) {
remove = false;
break;
}
}
if (!remove) {
QMessageBox confirm(this);
confirm.setWindowTitle("Delete media in use?");
confirm.setText("The media '" + m->name + "' is currently used in the sequence. Deleting it will remove all instances in the sequence. Are you sure you want to do this?");
QAbstractButton* yes_button = confirm.addButton(QMessageBox::Yes);
QAbstractButton* skip_button = confirm.addButton("Skip", QMessageBox::NoRole);
QAbstractButton* abort_button = confirm.addButton(QMessageBox::Abort);
confirm.exec();
if (confirm.clickedButton() == yes_button) {
// remove all clips referencing this media
for (int j=0;j<sequence->clip_count();j++) {
if (sequence->get_clip(j)->media == m) {
sequence->replace_clip(j, NULL);
QVector<QTreeWidgetItem*> parents;
QList<QTreeWidgetItem*> sequence_items;
QList<QTreeWidgetItem*> all_top_level_items;
for (int i=0;i<ui->treeWidget->topLevelItemCount();i++) {
all_top_level_items.append(ui->treeWidget->topLevelItem(i));
}
get_media_from_table(all_top_level_items, sequence_items, MEDIA_TYPE_SEQUENCE); // find all sequences in project
if (sequence_items.size() > 0) {
QList<QTreeWidgetItem*> media_items;
get_media_from_table(items, media_items, MEDIA_TYPE_FOOTAGE);
for (int i=0;i<media_items.size();i++) {
QTreeWidgetItem* item = media_items.at(i);
Media* media = get_media_from_tree(item);
bool confirm_delete = false;
for (int j=0;j<sequence_items.size();j++) {
Sequence* s = get_sequence_from_tree(sequence_items.at(j));
for (int k=0;k<s->clip_count();k++) {
Clip* c = s->get_clip(k);
if (c != NULL && c->media == media) {
if (!confirm_delete) {
// we found a reference, so we know we'll need to ask if the user wants to delete it
QMessageBox confirm(this);
confirm.setWindowTitle("Delete media in use?");
confirm.setText("The media '" + media->name + "' is currently used in '" + s->name + "'. Deleting it will remove all instances in the sequence. Are you sure you want to do this?");
QAbstractButton* yes_button = confirm.addButton(QMessageBox::Yes);
QAbstractButton* skip_button = confirm.addButton("Skip", QMessageBox::NoRole);
QAbstractButton* abort_button = confirm.addButton(QMessageBox::Abort);
confirm.exec();
if (confirm.clickedButton() == yes_button) {
// remove all clips referencing this media
confirm_delete = true;
redraw = true;
} else if (confirm.clickedButton() == skip_button) {
// remove media item and any folders containing it from the remove list
QTreeWidgetItem* parent = item;
while (parent != NULL) {
parents.append(parent);
// re-add item's siblings
for (int m=0;m<parent->childCount();m++) {
QTreeWidgetItem* child = parent->child(m);
bool found = false;
for (int n=0;n<items.size();n++) {
if (items.at(n) == child) {
found = true;
break;
}
}
if (!found) {
items.append(child);
}
}
parent = parent->parent();
}
j = sequence_items.size();
k = s->clip_count();
} else if (confirm.clickedButton() == abort_button) {
// break out of loop
i = media_items.size();
j = sequence_items.size();
k = s->clip_count();
remove = false;
}
}
if (confirm_delete) {
ta->delete_clip(s, k);
}
}
remove = true;
redraw = true;
} else if (confirm.clickedButton() == skip_button) {
items.removeAt(i);
i--;
remove = true;
} else if (confirm.clickedButton() == abort_button) {
break;
}
}
}
@@ -250,20 +305,38 @@ void Project::delete_selected_media() {
// remove
if (remove) {
for (int i=0;i<items.size();i++) {
QTreeWidgetItem* item = items.at(i);
delete_media(item);
delete item;
// remove media and parents
for (int m=0;m<parents.size();m++) {
for (int l=0;l<items.size();l++) {
if (items.at(l) == parents.at(m)) {
items.removeAt(l);
l--;
}
}
}
}
// redraw clips
if (redraw) {
panel_timeline->redraw_all_clips(true);
for (int i=0;i<items.size();i++) {
/*
delete_media(item);
delete item;*/
// send delete command to the TimelineAction
ta->delete_media(items.at(i));
}
undo_stack.push(ta);
// redraw clips
if (redraw) {
panel_timeline->redraw_all_clips(true);
}
} else {
delete ta;
}
}
void Project::process_file_list(QStringList& files) {
bool imported = false;
TimelineAction* ta = new TimelineAction();
for (int i=0;i<files.count();i++) {
QString file(files.at(i));
@@ -301,7 +374,13 @@ void Project::process_file_list(QStringList& files) {
}
}
ui->treeWidget->addTopLevelItem(import_file(file));
ta->add_media(import_file(file));
imported = true;
}
if (imported) {
undo_stack.push(ta);
} else {
delete ta;
}
}
@@ -428,6 +507,8 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
folder->setData(0, Qt::UserRole + 3, attr.value().toInt());
} else if (attr.name() == "name") {
folder->setText(0, attr.value().toString());
} else if (attr.name() == "parent") {
folder->setData(0, Qt::UserRole + 4, attr.value().toInt());
}
}
loaded_folders.append(folder);
@@ -644,6 +725,16 @@ void Project::load_project() {
// load media
if (cont) {
// since folders loaded correctly, organize them appropriately
for (int i=0;i<loaded_folders.size();i++) {
QTreeWidgetItem* folder = loaded_folders.at(i);
int parent = folder->data(0, Qt::UserRole + 4).toInt();
if (parent > 0) {
ui->treeWidget->takeTopLevelItem(ui->treeWidget->indexOfTopLevelItem(folder));
find_loaded_folder_by_id(parent)->addChild(folder);
}
}
cont = load_worker(file, stream, MEDIA_TYPE_FOOTAGE);
}
@@ -668,8 +759,6 @@ void Project::load_project() {
}
file.close();
add_recent_project(project_url);
}
void Project::save_folder(QXmlStreamWriter& stream, QTreeWidgetItem* parent, int type) {
@@ -679,14 +768,20 @@ void Project::save_folder(QXmlStreamWriter& stream, QTreeWidgetItem* parent, int
QTreeWidgetItem* item = root ? ui->treeWidget->topLevelItem(i) : parent->child(i);
int item_type = get_type_from_tree(item);
if (item_type == MEDIA_TYPE_FOLDER) {
if (type == MEDIA_TYPE_FOLDER) {
if (type == SAVE_SET_FOLDER_IDS) {
item->setData(0, Qt::UserRole + 3, folder_id); // saves a temporary ID for matching in the project file
folder_id++;
} else if (type == MEDIA_TYPE_FOLDER) {
// if we're saving folders, save the folder
stream.writeStartElement("folder");
stream.writeAttribute("name", item->text(0));
stream.writeAttribute("id", QString::number(folder_id));
item->setData(0, Qt::UserRole + 3, folder_id); // saves a temporary ID for matching in the project file
stream.writeEndElement();
folder_id++;
stream.writeAttribute("id", QString::number(item->data(0, Qt::UserRole + 3).toInt()));
if (item->parent() == NULL) {
stream.writeAttribute("parent", "0");
} else {
stream.writeAttribute("parent", QString::number(item->parent()->data(0, Qt::UserRole + 3).toInt()));
}
stream.writeEndElement();
}
save_folder(stream, item, type);
} else if (type == item_type) {
@@ -777,6 +872,8 @@ void Project::save_project() {
stream.writeTextElement("version", SAVE_VERSION);
save_folder(stream, NULL, SAVE_SET_FOLDER_IDS);
stream.writeStartElement("folders"); // folders
save_folder(stream, NULL, MEDIA_TYPE_FOLDER);
stream.writeEndElement(); // folders
@@ -795,8 +892,6 @@ void Project::save_project() {
file.close();
add_recent_project(project_url);
project_changed = false;
}
+4 -2
View File
@@ -14,7 +14,7 @@ class QXmlStreamWriter;
class QXmlStreamReader;
class QFile;
#define SAVE_VERSION "180711"
#define SAVE_VERSION "180715"
#define MEDIA_TYPE_FOOTAGE 0
#define MEDIA_TYPE_SEQUENCE 1
@@ -22,6 +22,7 @@ class QFile;
#define MEDIA_TYPE_SOLID 3
#define LOAD_TYPE_VERSION 69
#define SAVE_SET_FOLDER_IDS 70
namespace Ui {
class Project;
@@ -62,6 +63,7 @@ public:
Sequence* get_sequence_from_tree(QTreeWidgetItem* item);
void set_sequence_of_tree(QTreeWidgetItem* item, Sequence* sequence);
void set_item_to_folder(QTreeWidgetItem* item);
void save_recent_projects();
SourceTable* source_table;
private:
@@ -76,7 +78,7 @@ private:
QVector<Media*> loaded_media;
QTreeWidgetItem* find_loaded_folder_by_id(int id);
void add_recent_project(QString url);
void save_recent_projects();
void get_media_from_table(QList<QTreeWidgetItem*> items, QList<QTreeWidgetItem*>& list, int type);
private slots:
void rename_media(QTreeWidgetItem* item, int column);
void clear_recent_projects();
+15 -15
View File
@@ -354,8 +354,8 @@ void Timeline::ripple(TimelineAction* ta, long ripple_point, long ripple_length)
for (int i=0;i<sequence->clip_count();i++) {
Clip* c = sequence->get_clip(i);
if (c != NULL && c->timeline_in >= ripple_point) {
ta->increase_timeline_in(i, ripple_length);
ta->increase_timeline_out(i, ripple_length);
ta->increase_timeline_in(sequence, i, ripple_length);
ta->increase_timeline_out(sequence, i, ripple_length);
}
}
@@ -415,7 +415,7 @@ Clip* Timeline::split_clip(TimelineAction* ta, int p, long frame) {
if (pre != NULL && pre->timeline_in < frame && pre->timeline_out > frame) { // guard against attempts to split at in/out points
Clip* post = pre->copy();
ta->set_timeline_out(p, frame);
ta->set_timeline_out(sequence, p, frame);
post->timeline_in = frame;
post->clip_in = pre->clip_in + (frame - pre->timeline_in);
@@ -490,7 +490,7 @@ bool Timeline::split_clip_and_relink(TimelineAction* ta, int clip, long frame, b
relink_clips_using_ids(pre_clips, post_clips);
}
ta->add_clips(post_clips);
ta->add_clips(sequence, post_clips);
return true;
}
}
@@ -540,14 +540,14 @@ void Timeline::delete_areas_and_relink(TimelineAction* ta, QVector<Selection>& a
if (c != NULL && c->track == s.track && !c->undeletable) {
if (c->timeline_in >= s.in && c->timeline_out <= s.out) {
// clips falls entirely within deletion area
ta->delete_clip(j);
ta->delete_clip(sequence, j);
} else if (c->timeline_in < s.in && c->timeline_out > s.out) {
// middle of clip is within deletion area
// duplicate clip
Clip* post = c->copy();
ta->set_timeline_out(j, s.in);
ta->set_timeline_out(sequence, j, s.in);
post->timeline_in = s.out;
post->clip_in = c->clip_in + (s.in - c->timeline_in) + (s.out - s.in);
@@ -555,17 +555,17 @@ void Timeline::delete_areas_and_relink(TimelineAction* ta, QVector<Selection>& a
post_clips.append(post);
} else if (c->timeline_in < s.in && c->timeline_out > s.in) {
// only out point is in deletion area
ta->set_timeline_out(j, s.in);
ta->set_timeline_out(sequence, j, s.in);
} else if (c->timeline_in < s.out && c->timeline_out > s.out) {
// only in point is in deletion area
ta->increase_clip_in(j, s.out - c->timeline_in);
ta->set_timeline_in(j, s.out);
ta->increase_clip_in(sequence, j, s.out - c->timeline_in);
ta->set_timeline_in(sequence, j, s.out);
}
}
}
}
relink_clips_using_ids(pre_clips, post_clips);
ta->add_clips(post_clips);
ta->add_clips(sequence, post_clips);
}
void Timeline::copy(bool del) {
@@ -683,7 +683,7 @@ void Timeline::paste() {
}
// ADAPT
ta->add_clips(pasted_clips);
ta->add_clips(sequence, pasted_clips);
undo_stack.push(ta);
@@ -723,7 +723,7 @@ bool Timeline::split_selection(TimelineAction* ta) {
split_B->timeline_in = s.out;
secondary_post_splits.append(split_B);
ta->set_timeline_out(j, s.in);
ta->set_timeline_out(sequence, j, s.in);
split = true;
} else {
Clip* post_a = split_clip(ta, j, s.in);
@@ -752,8 +752,8 @@ bool Timeline::split_selection(TimelineAction* ta) {
// relink after splitting
relink_clips_using_ids(pre_splits, post_splits);
relink_clips_using_ids(pre_splits, secondary_post_splits);
ta->add_clips(post_splits);
ta->add_clips(secondary_post_splits);
ta->add_clips(sequence, post_splits);
ta->add_clips(sequence, secondary_post_splits);
return true;
}
@@ -784,7 +784,7 @@ void Timeline::split_at_playhead() {
if (split_selected) {
// relink clips if we split
relink_clips_using_ids(pre_clips, post_clips);
ta->add_clips(post_clips);
ta->add_clips(sequence, post_clips);
} else {
// split a selection if not
split_selected = split_selection(ta);
+2 -2
View File
@@ -33,8 +33,8 @@ bool Effect::is_enabled() {
}
Effect* Effect::copy(Clip*) {return NULL;}
void Effect::load(QXmlStreamReader* stream) {}
void Effect::save(QXmlStreamWriter* stream) {}
void Effect::load(QXmlStreamReader*) {}
void Effect::save(QXmlStreamWriter*) {}
/*void Effect::import_values(float* val, int count) {
qDebug() << "[ERROR] import_values MUST be overridden";
}
+129 -48
View File
@@ -1,6 +1,14 @@
#include "undo.h"
#include <QDebug>
#include <QTreeWidgetItem>
#include "project/clip.h"
#include "project/sequence.h"
#include "panels/panels.h"
#include "panels/project.h"
#include "playback/playback.h"
#include "ui/sourcetable.h"
QUndoStack undo_stack;
@@ -24,6 +32,15 @@ TimelineAction::~TimelineAction() {
for (int i=0;i<deleted_clips.size();i++) {
delete deleted_clips.at(i);
}
for (int i=0;i<deleted_media.size();i++) {
panel_project->delete_media(deleted_media.at(i));
delete deleted_media.at(i);
}
} else {
/*for (int i=0;i<media_to_add.size();i++) {
panel_project->delete_media(media_to_add.at(i));
delete media_to_add.at(i);
}*/
}
}
@@ -36,103 +53,130 @@ void TimelineAction::offset_links(QVector<Clip*>& clips, int offset) {
}
}
void TimelineAction::add_clips(QVector<Clip*>& add) {
void TimelineAction::add_clips(Sequence* s, QVector<Clip*>& add) {
offset_links(add, clips_to_add.size());
clips_to_add.append(add);
for (int i=0;i<clips_to_add.size();i++) {
sequence_to_add_clips_to.append(s);
}
}
void TimelineAction::new_action(int action, int clip, long old_val, long new_val) {
void TimelineAction::new_action(Sequence* s, int action, int clip, long old_val, long new_val) {
sequences.append(s);
actions.append(action);
clips.append(clip);
old_values.append(old_val);
new_values.append(new_val);
}
void TimelineAction::set_timeline_in(int clip, long value) {
new_action(TA_IN, clip, sequence->get_clip(clip)->timeline_in, value);
void TimelineAction::set_timeline_in(Sequence* s, int clip, long value) {
new_action(s, TA_IN, clip, s->get_clip(clip)->timeline_in, value);
}
void TimelineAction::set_timeline_out(int clip, long value) {
new_action(TA_OUT, clip, sequence->get_clip(clip)->timeline_out, value);
void TimelineAction::set_timeline_out(Sequence* s, int clip, long value) {
new_action(s, TA_OUT, clip, s->get_clip(clip)->timeline_out, value);
}
void TimelineAction::set_clip_in(int clip, long value) {
new_action(TA_CLIP_IN, clip, sequence->get_clip(clip)->clip_in, value);
void TimelineAction::set_clip_in(Sequence* s, int clip, long value) {
new_action(s, TA_CLIP_IN, clip, s->get_clip(clip)->clip_in, value);
}
void TimelineAction::set_track(int clip, int value) {
new_action(TA_TRACK, clip, sequence->get_clip(clip)->track, value);
void TimelineAction::set_track(Sequence* s, int clip, int value) {
new_action(s, TA_TRACK, clip, s->get_clip(clip)->track, value);
}
void TimelineAction::increase_timeline_in(int clip, long value) {
new_action(TA_ADD_IN, clip, 0, value);
void TimelineAction::increase_timeline_in(Sequence* s, int clip, long value) {
new_action(s, TA_ADD_IN, clip, 0, value);
}
void TimelineAction::increase_timeline_out(int clip, long value) {
new_action(TA_ADD_OUT, clip, 0, value);
void TimelineAction::increase_timeline_out(Sequence* s, int clip, long value) {
new_action(s, TA_ADD_OUT, clip, 0, value);
}
void TimelineAction::increase_clip_in(int clip, long value) {
new_action(TA_ADD_CLIP_IN, clip, 0, value);
void TimelineAction::increase_clip_in(Sequence* s, int clip, long value) {
new_action(s, TA_ADD_CLIP_IN, clip, 0, value);
}
void TimelineAction::increase_track(int clip, int value) {
new_action(TA_ADD_TRACK, clip, 0, value);
void TimelineAction::increase_track(Sequence* s, int clip, int value) {
new_action(s, TA_ADD_TRACK, clip, 0, value);
}
void TimelineAction::delete_clip(int clip) {
new_action(TA_DELETE, clip, 0, 0);
void TimelineAction::delete_clip(Sequence* s, int clip) {
new_action(s, TA_DELETE, clip, 0, 0);
}
void TimelineAction::add_media(QTreeWidgetItem* item) {
media_to_add.append(item);
}
void TimelineAction::delete_media(QTreeWidgetItem* item) {
deleted_media.append(item);
}
void TimelineAction::undo() {
for (int i=0;i<deleted_media.size();i++) {
QTreeWidgetItem* item = deleted_media.at(i);
QTreeWidgetItem* parent = deleted_media_parents.at(i);
if (parent == NULL) {
panel_project->source_table->addTopLevelItem(item);
} else {
parent->addChild(item);
}
}
for (int i=0;i<actions.size();i++) {
switch (actions.at(i)) {
case TA_IN:
sequence->get_clip(clips.at(i))->timeline_in = old_values.at(i);
sequences.at(i)->get_clip(clips.at(i))->timeline_in = old_values.at(i);
break;
case TA_OUT:
sequence->get_clip(clips.at(i))->timeline_out = old_values.at(i);
sequences.at(i)->get_clip(clips.at(i))->timeline_out = old_values.at(i);
break;
case TA_CLIP_IN:
sequence->get_clip(clips.at(i))->clip_in = old_values.at(i);
sequences.at(i)->get_clip(clips.at(i))->clip_in = old_values.at(i);
break;
case TA_TRACK:
sequence->get_clip(clips.at(i))->track = old_values.at(i);
sequences.at(i)->get_clip(clips.at(i))->track = old_values.at(i);
break;
case TA_DELETE:
sequence->replace_clip(clips.at(i), deleted_clips.at(new_values.at(i)));
sequences.at(i)->replace_clip(clips.at(i), deleted_clips.at(new_values.at(i)));
break;
case TA_ADD_IN:
sequence->get_clip(clips.at(i))->timeline_in -= new_values.at(i);
sequences.at(i)->get_clip(clips.at(i))->timeline_in -= new_values.at(i);
break;
case TA_ADD_OUT:
sequence->get_clip(clips.at(i))->timeline_out -= new_values.at(i);
sequences.at(i)->get_clip(clips.at(i))->timeline_out -= new_values.at(i);
break;
case TA_ADD_CLIP_IN:
sequence->get_clip(clips.at(i))->clip_in -= new_values.at(i);
sequences.at(i)->get_clip(clips.at(i))->clip_in -= new_values.at(i);
break;
case TA_ADD_TRACK:
sequence->get_clip(clips.at(i))->track -= new_values.at(i);
sequences.at(i)->get_clip(clips.at(i))->track -= new_values.at(i);
break;
}
}
// restore link references to deleted clips
for (int i=0;i<removed_link_to.size();i++) {
sequence->get_clip(removed_link_from.at(i))->linked.append(removed_link_to.at(i));
removed_link_from_sequence.at(i)->get_clip(removed_link_from.at(i))->linked.append(removed_link_to.at(i));
}
// delete added clips
if (clips_to_add.size() > 0) {
int delete_count = 0;
for (int i=0;i<clips_to_add.size();i++) {
sequence->destroy_clip(added_indexes.at(i)-delete_count, true);
sequence_to_add_clips_to.at(i)->destroy_clip(added_indexes.at(i)-delete_count, true);
delete_count++;
}
}
// remove any added media
if (media_to_add.size() > 0) {
for (int i=0;i<media_to_add.size();i++) {
panel_project->source_table->takeTopLevelItem(panel_project->source_table->indexOfTopLevelItem(media_to_add.at(i)));
}
}
done = false;
}
@@ -141,56 +185,60 @@ void TimelineAction::redo() {
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();
for (int i=0;i<actions.size();i++) {
switch (actions.at(i)) {
case TA_IN:
{
sequence->get_clip(clips.at(i))->timeline_in = new_values.at(i);
sequences.at(i)->get_clip(clips.at(i))->timeline_in = new_values.at(i);
}
break;
case TA_OUT:
{
sequence->get_clip(clips.at(i))->timeline_out = new_values.at(i);
sequences.at(i)->get_clip(clips.at(i))->timeline_out = new_values.at(i);
}
break;
case TA_CLIP_IN:
{
sequence->get_clip(clips.at(i))->clip_in = new_values.at(i);
sequences.at(i)->get_clip(clips.at(i))->clip_in = new_values.at(i);
}
break;
case TA_TRACK:
{
sequence->get_clip(clips.at(i))->track = new_values.at(i);
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(sequence->get_clip(clips.at(i)));
deleted_clips.append(sequences.at(i)->get_clip(clips.at(i)));
deleted_clips_indices.append(clips.at(i));
sequence->replace_clip(clips.at(i), NULL);
deleted_clip_sequences.append(sequences.at(i));
sequences.at(i)->replace_clip(clips.at(i), NULL);
}
break;
case TA_ADD_IN:
{
sequence->get_clip(clips.at(i))->timeline_in += new_values.at(i);
sequences.at(i)->get_clip(clips.at(i))->timeline_in += new_values.at(i);
}
break;
case TA_ADD_OUT:
{
sequence->get_clip(clips.at(i))->timeline_out += new_values.at(i);
sequences.at(i)->get_clip(clips.at(i))->timeline_out += new_values.at(i);
}
break;
case TA_ADD_CLIP_IN:
{
sequence->get_clip(clips.at(i))->clip_in += new_values.at(i);
sequences.at(i)->get_clip(clips.at(i))->clip_in += new_values.at(i);
}
break;
case TA_ADD_TRACK:
{
sequence->get_clip(clips.at(i))->track += new_values.at(i);
sequences.at(i)->get_clip(clips.at(i))->track += new_values.at(i);
}
break;
}
@@ -198,11 +246,13 @@ void TimelineAction::redo() {
// remove any potential link references from deleted clips
for (int i=0;i<deleted_clips_indices.size();i++) {
for (int j=0;j<sequence->clip_count();j++) {
Clip* c = sequence->get_clip(j);
Sequence* s = deleted_clip_sequences.at(i);
for (int j=0;j<s->clip_count();j++) {
Clip* c = s->get_clip(j);
if (c != NULL) {
for (int k=0;k<c->linked.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);
@@ -215,15 +265,46 @@ void TimelineAction::redo() {
// add any new clips
if (clips_to_add.size() > 0) {
int link_offset = sequence->clip_count();
QVector<Clip*> copies;
for (int i=0;i<clips_to_add.size();i++) {
Clip* original = clips_to_add.at(i);
Clip* copy = original->copy();
copy->linked.resize(original->linked.size());
for (int j=0;j<original->linked.size();j++) {
copy->linked[j] = original->linked.at(j) + link_offset;
copy->linked[j] = original->linked.at(j) + sequence_to_add_clips_to.at(i)->clip_count();
}
added_indexes.append(sequence->add_clip(copy));
copies.append(copy);
}
for (int i=0;i<clips_to_add.size();i++) {
added_indexes.append(sequence_to_add_clips_to.at(i)->add_clip(copies.at(i)));
}
}
// delete media
if (deleted_media.size() > 0) {
for (int i=0;i<deleted_media.size();i++) {
QTreeWidgetItem* item = deleted_media.at(i);
deleted_media_parents.append(item->parent());
// if we're deleting the open sequence, close it
if (panel_project->get_type_from_tree(item) == MEDIA_TYPE_SEQUENCE) {
if (panel_project->get_sequence_from_tree(item) == sequence) {
set_sequence(NULL);
}
}
if (item->parent() == NULL) {
panel_project->source_table->takeTopLevelItem(panel_project->source_table->indexOfTopLevelItem(item));
} else {
item->parent()->removeChild(item);
}
}
}
// add any new media
if (media_to_add.size() > 0) {
for (int i=0;i<media_to_add.size();i++) {
panel_project->source_table->addTopLevelItem(media_to_add.at(i));
}
}
+29 -18
View File
@@ -1,32 +1,38 @@
#ifndef UNDO_H
#define UNDO_H
class QTreeWidgetItem;
class Clip;
class Sequence;
#include <QUndoStack>
#include <QUndoCommand>
#include <QVector>
#include "project/clip.h"
#include "project/sequence.h"
extern QUndoStack undo_stack;
class TimelineAction : public QUndoCommand {
public:
TimelineAction();
~TimelineAction();
void add_clips(QVector<Clip*>& add);
void set_timeline_in(int clip, long value);
void increase_timeline_in(int clip, long value);
void set_timeline_out(int clip, long value);
void increase_timeline_out(int clip, long value);
void set_clip_in(int clip, long value);
void increase_clip_in(int clip, long value);
void set_track(int clip, int value);
void increase_track(int clip, int value);
void delete_clip(int clip);
void add_clips(Sequence* s, QVector<Clip*>& add);
void set_timeline_in(Sequence* s, int clip, long value);
void increase_timeline_in(Sequence* s, int clip, long value);
void set_timeline_out(Sequence* s, int clip, long value);
void increase_timeline_out(Sequence* s, int clip, long value);
void set_clip_in(Sequence* s, int clip, long value);
void increase_clip_in(Sequence* s, int clip, long value);
void set_track(Sequence* s, int clip, int value);
void increase_track(Sequence* s, int clip, int value);
void delete_clip(Sequence* s, int clip);
void add_media(QTreeWidgetItem* item);
void delete_media(QTreeWidgetItem* item);
void undo();
void redo();
private:
bool done;
QVector<Sequence*> sequences;
QVector<int> actions;
QVector<int> clips;
QVector<long> old_values;
@@ -34,18 +40,23 @@ private:
QVector<Clip*> deleted_clips;
QVector<int> deleted_clips_indices;
QVector<Sequence*> deleted_clip_sequences;
QVector<Sequence*> sequence_to_add_clips_to;
QVector<Clip*> clips_to_add;
QVector<int> added_indexes;
void new_action(int action, int clip, long old_val, long new_val);
void offset_links(QVector<Clip*>& clips, int offset);
QVector<Sequence*> removed_link_from_sequence;
QVector<int> removed_link_from;
QVector<int> removed_link_to;
bool done;
QVector<QTreeWidgetItem*> deleted_media;
QVector<QTreeWidgetItem*> deleted_media_parents;
QVector<QTreeWidgetItem*> media_to_add;
void new_action(Sequence* s, int action, int clip, long old_val, long new_val);
void offset_links(QVector<Clip*>& clips, int offset);
};
#endif // UNDO_H
+2 -2
View File
@@ -60,7 +60,7 @@ void LabelSlider::mousePressEvent(QMouseEvent *ev) {
}
}
void LabelSlider::mouseMoveEvent(QMouseEvent *ev) {
void LabelSlider::mouseMoveEvent(QMouseEvent*) {
if (drag_start) {
set_value(internal_value + (cursor().pos().x()-drag_start_x) + (drag_start_y-cursor().pos().y()));
cursor().setPos(drag_start_x, drag_start_y);
@@ -68,7 +68,7 @@ void LabelSlider::mouseMoveEvent(QMouseEvent *ev) {
}
}
void LabelSlider::mouseReleaseEvent(QMouseEvent *ev) {
void LabelSlider::mouseReleaseEvent(QMouseEvent*) {
if (drag_start) {
qApp->restoreOverrideCursor();
drag_start = false;
+61 -19
View File
@@ -6,6 +6,7 @@
#include "panels/viewer.h"
#include "panels/panels.h"
#include "playback/playback.h"
#include "project/undo.h"
#include <QDragEnterEvent>
#include <QMimeData>
@@ -71,6 +72,7 @@ void SourceTable::dragMoveEvent(QDragMoveEvent *event) {
void SourceTable::dropEvent(QDropEvent* event) {
const QMimeData* mimeData = event->mimeData();
if (mimeData->hasUrls()) {
// drag files in from outside
QList<QUrl> urls = mimeData->urls();
if (!urls.isEmpty()) {
QStringList paths;
@@ -82,33 +84,73 @@ void SourceTable::dropEvent(QDropEvent* event) {
}
event->acceptProposedAction();
} else {
QTreeWidgetItem* item = itemAt(event->pos());
if (item == NULL || (item != NULL && panel_project->get_type_from_tree(item) == MEDIA_TYPE_FOLDER)) {
QList<QTreeWidgetItem*> items = selectedItems();
for (int i=0;i<items.size();i++) {
QTreeWidgetItem* s = items.at(i);
// dragging files within project
QVector<QTreeWidgetItem*> move_items;
QTreeWidgetItem* drop_item = itemAt(event->pos());
// if we dragged to the root OR dragged to a folder
if (drop_item == NULL || (drop_item != NULL && panel_project->get_type_from_tree(drop_item) == MEDIA_TYPE_FOLDER)) {
QList<QTreeWidgetItem*> selected_items = selectedItems();
for (int i=0;i<selected_items.size();i++) {
QTreeWidgetItem* s = selected_items.at(i);
bool ignore = false;
if (s->parent() == NULL) {
takeTopLevelItem(indexOfTopLevelItem(s));
} else {
if (s->parent() != NULL) {
// if child belongs to a selected parent, assume the user is just moving the parent and ignore the child
for (int j=0;j<items.size();j++) {
if (s->parent() == items.at(j)) {
ignore = true;
break;
QTreeWidgetItem* par = s->parent();
while (par != NULL) {
for (int j=0;j<selected_items.size();j++) {
if (par == selected_items.at(j)) {
ignore = true;
break;
}
}
par = par->parent();
}
if (!ignore) s->parent()->takeChild(s->parent()->indexOfChild(s));
}
if (!ignore) {
if (item == NULL) {
addTopLevelItem(s);
} else {
item->addChild(s);
}
move_items.append(s);
}
}
project_changed = true;
if (move_items.size() > 0) {
MediaMove* mm = new MediaMove(this);
mm->to = drop_item;
mm->items = move_items;
undo_stack.push(mm);
project_changed = true;
}
}
}
}
MediaMove::MediaMove(SourceTable *s) : table(s) {}
void MediaMove::undo() {
for (int i=0;i<items.size();i++) {
if (to == NULL) {
table->takeTopLevelItem(table->indexOfTopLevelItem(items.at(i)));
} else {
to->removeChild(items.at(i));
}
if (froms.at(i) == NULL) {
table->addTopLevelItem(items.at(i));
} else {
froms.at(i)->addChild(items.at(i));
}
}
}
void MediaMove::redo() {
for (int i=0;i<items.size();i++) {
QTreeWidgetItem* parent = items.at(i)->parent();
froms.append(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));
}
}
}
+13
View File
@@ -3,6 +3,7 @@
#include <QTreeWidget>
#include <QTimer>
#include <QUndoCommand>
class Project;
@@ -26,4 +27,16 @@ private slots:
void stop_rename_timer();
};
class MediaMove : public QUndoCommand {
public:
MediaMove(SourceTable* s);
QVector<QTreeWidgetItem*> items;
QTreeWidgetItem* to;
void undo();
void redo();
private:
QVector<QTreeWidgetItem*> froms;
SourceTable* table;
};
#endif // SOURCETABLE_H
+6 -6
View File
@@ -188,7 +188,7 @@ void TimelineWidget::dropEvent(QDropEvent* event) {
}
}
ta->add_clips(added_clips);
ta->add_clips(sequence, added_clips);
panel_timeline->ghosts.clear();
panel_timeline->importing = false;
@@ -388,7 +388,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
panel_timeline->relink_clips_using_ids(old_clips, new_clips);
for (int i=0;i<new_clips.size();i++) {
ta->add_clips(new_clips);
ta->add_clips(sequence, new_clips);
}
}
} else {
@@ -417,10 +417,10 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
Ghost& g = panel_timeline->ghosts[i];
// step 3 - move clips
ta->increase_timeline_in(g.clip, g.in - g.old_in);
ta->increase_timeline_out(g.clip, g.out - g.old_out);
ta->increase_track(g.clip, g.track - g.old_track);
ta->increase_clip_in(g.clip, g.clip_in - g.old_clip_in);
ta->increase_timeline_in(sequence, g.clip, g.in - g.old_in);
ta->increase_timeline_out(sequence, g.clip, g.out - g.old_out);
ta->increase_track(sequence, g.clip, g.track - g.old_track);
ta->increase_clip_in(sequence, g.clip, g.clip_in - g.old_clip_in);
}
}