diff --git a/dialogs/loaddialog.cpp b/dialogs/loaddialog.cpp index 8e8522102..1d25a9fa8 100644 --- a/dialogs/loaddialog.cpp +++ b/dialogs/loaddialog.cpp @@ -11,6 +11,7 @@ #include "io/loadthread.h" #include "playback/playback.h" #include "ui/sourcetable.h" +#include "mainwindow.h" LoadDialog::LoadDialog(QWidget *parent, bool autorecovery) : QDialog(parent) { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); @@ -21,11 +22,11 @@ LoadDialog::LoadDialog(QWidget *parent, bool autorecovery) : QDialog(parent) { layout->addWidget(new QLabel("Loading '" + project_url.mid(project_url.lastIndexOf('/')+1) + "'...")); bar = new QProgressBar(); - bar->setValue(50); + bar->setValue(0); layout->addWidget(bar); cancel_button = new QPushButton("Cancel"); - connect(cancel_button, SIGNAL(clicked(bool)), this, SLOT(reject())); + connect(cancel_button, SIGNAL(clicked(bool)), this, SLOT(cancel())); hboxLayout = new QHBoxLayout(); hboxLayout->addStretch(); @@ -36,12 +37,19 @@ LoadDialog::LoadDialog(QWidget *parent, bool autorecovery) : QDialog(parent) { update(); - LoadThread* lt = new LoadThread(this, autorecovery); + lt = new LoadThread(this, autorecovery); QObject::connect(lt, SIGNAL(success()), this, SLOT(thread_done())); + QObject::connect(lt, SIGNAL(report_progress(int)), bar, SLOT(setValue(int))); lt->start(); } +void LoadDialog::cancel() { + lt->cancel(); + lt->wait(); + mainWindow->new_project(); + reject(); +} + void LoadDialog::thread_done() { -// project_model.update_data(); - close(); + accept(); } diff --git a/dialogs/loaddialog.h b/dialogs/loaddialog.h index 2f646fc91..c9099c66d 100644 --- a/dialogs/loaddialog.h +++ b/dialogs/loaddialog.h @@ -8,6 +8,7 @@ class Sequence; class Media; class Footage; class QHBoxLayout; +class LoadThread; class LoadDialog : public QDialog { @@ -15,11 +16,13 @@ class LoadDialog : public QDialog public: LoadDialog(QWidget* parent, bool autorecovery); private slots: + void cancel(); void thread_done(); private: QProgressBar* bar; QPushButton* cancel_button; QHBoxLayout* hboxLayout; + LoadThread* lt; }; #endif // LOADDIALOG_H diff --git a/effects/internal/cornerpineffect.cpp b/effects/internal/cornerpineffect.cpp index cea4e3d3a..96069b0bf 100644 --- a/effects/internal/cornerpineffect.cpp +++ b/effects/internal/cornerpineffect.cpp @@ -28,20 +28,20 @@ CornerPinEffect::CornerPinEffect(Clip *c, const EffectMeta *em) : Effect(c, em) perspective->set_bool_value(true); top_left_gizmo = add_gizmo(GIZMO_TYPE_DOT); - top_left_gizmo->x_field = top_left_x; - top_left_gizmo->y_field = top_left_y; + top_left_gizmo->x_field1 = top_left_x; + top_left_gizmo->y_field1 = top_left_y; top_right_gizmo = add_gizmo(GIZMO_TYPE_DOT); - top_right_gizmo->x_field = top_right_x; - top_right_gizmo->y_field = top_right_y; + top_right_gizmo->x_field1 = top_right_x; + top_right_gizmo->y_field1 = top_right_y; bottom_left_gizmo = add_gizmo(GIZMO_TYPE_DOT); - bottom_left_gizmo->x_field = bottom_left_x; - bottom_left_gizmo->y_field = bottom_left_y; + bottom_left_gizmo->x_field1 = bottom_left_x; + bottom_left_gizmo->y_field1 = bottom_left_y; bottom_right_gizmo = add_gizmo(GIZMO_TYPE_DOT); - bottom_right_gizmo->x_field = bottom_right_x; - bottom_right_gizmo->y_field = bottom_right_y; + bottom_right_gizmo->x_field1 = bottom_right_x; + bottom_right_gizmo->y_field1 = bottom_right_y; vertPath = "cornerpin.vert"; fragPath = "cornerpin.frag"; diff --git a/effects/internal/transformeffect.cpp b/effects/internal/transformeffect.cpp index da03ea718..42b54497c 100644 --- a/effects/internal/transformeffect.cpp +++ b/effects/internal/transformeffect.cpp @@ -68,49 +68,51 @@ TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) // set up gizmos top_left_gizmo = add_gizmo(GIZMO_TYPE_DOT); top_left_gizmo->set_cursor(Qt::SizeFDiagCursor); - top_left_gizmo->x_field = scale_x; + top_left_gizmo->x_field1 = scale_x; top_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); top_center_gizmo->set_cursor(Qt::SizeVerCursor); - top_center_gizmo->y_field = scale_x; + top_center_gizmo->y_field1 = scale_x; top_right_gizmo = add_gizmo(GIZMO_TYPE_DOT); top_right_gizmo->set_cursor(Qt::SizeBDiagCursor); - top_right_gizmo->x_field = scale_x; + top_right_gizmo->x_field1 = scale_x; bottom_left_gizmo = add_gizmo(GIZMO_TYPE_DOT); bottom_left_gizmo->set_cursor(Qt::SizeBDiagCursor); - bottom_left_gizmo->x_field = scale_x; + bottom_left_gizmo->x_field1 = scale_x; bottom_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); bottom_center_gizmo->set_cursor(Qt::SizeVerCursor); - bottom_center_gizmo->y_field = scale_x; + bottom_center_gizmo->y_field1 = scale_x; bottom_right_gizmo = add_gizmo(GIZMO_TYPE_DOT); bottom_right_gizmo->set_cursor(Qt::SizeFDiagCursor); - bottom_right_gizmo->x_field = scale_x; + bottom_right_gizmo->x_field1 = scale_x; left_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); left_center_gizmo->set_cursor(Qt::SizeHorCursor); - left_center_gizmo->x_field = scale_x; + left_center_gizmo->x_field1 = scale_x; right_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); right_center_gizmo->set_cursor(Qt::SizeHorCursor); - right_center_gizmo->x_field = scale_x; + right_center_gizmo->x_field1 = scale_x; anchor_gizmo = add_gizmo(GIZMO_TYPE_TARGET); anchor_gizmo->set_cursor(Qt::SizeAllCursor); - anchor_gizmo->x_field = anchor_x_box; - anchor_gizmo->y_field = anchor_y_box; + anchor_gizmo->x_field1 = anchor_x_box; + anchor_gizmo->y_field1 = anchor_y_box; + anchor_gizmo->x_field2 = position_x; + anchor_gizmo->y_field2 = position_y; rotate_gizmo = add_gizmo(GIZMO_TYPE_DOT); rotate_gizmo->color = Qt::green; rotate_gizmo->set_cursor(Qt::SizeAllCursor); - rotate_gizmo->x_field = rotation; + rotate_gizmo->x_field1 = rotation; rect_gizmo = add_gizmo(GIZMO_TYPE_POLY); - rect_gizmo->x_field = position_x; - rect_gizmo->y_field = position_y; + rect_gizmo->x_field1 = position_x; + rect_gizmo->y_field1 = position_y; connect(uniform_scale_field, SIGNAL(toggled(bool)), this, SLOT(toggle_uniform_scale(bool))); @@ -142,31 +144,31 @@ void TransformEffect::refresh() { double x_percent_multipler = 200.0 / parent_clip->sequence->width; double y_percent_multipler = 200.0 / parent_clip->sequence->height; - top_left_gizmo->x_field_multi = -x_percent_multipler; - top_left_gizmo->y_field_multi = -y_percent_multipler; - top_center_gizmo->y_field_multi = -y_percent_multipler; - top_right_gizmo->x_field_multi = x_percent_multipler; - top_right_gizmo->y_field_multi = -y_percent_multipler; - bottom_left_gizmo->x_field_multi = -x_percent_multipler; - bottom_left_gizmo->y_field_multi = y_percent_multipler; - bottom_center_gizmo->y_field_multi = y_percent_multipler; - bottom_right_gizmo->x_field_multi = x_percent_multipler; - bottom_right_gizmo->y_field_multi = y_percent_multipler; - left_center_gizmo->x_field_multi = -x_percent_multipler; - right_center_gizmo->x_field_multi = x_percent_multipler; - rotate_gizmo->x_field_multi = x_percent_multipler; + top_left_gizmo->x_field_multi1 = -x_percent_multipler; + top_left_gizmo->y_field_multi1 = -y_percent_multipler; + top_center_gizmo->y_field_multi1 = -y_percent_multipler; + top_right_gizmo->x_field_multi1 = x_percent_multipler; + top_right_gizmo->y_field_multi1 = -y_percent_multipler; + bottom_left_gizmo->x_field_multi1 = -x_percent_multipler; + bottom_left_gizmo->y_field_multi1 = y_percent_multipler; + bottom_center_gizmo->y_field_multi1 = y_percent_multipler; + bottom_right_gizmo->x_field_multi1 = x_percent_multipler; + bottom_right_gizmo->y_field_multi1 = y_percent_multipler; + left_center_gizmo->x_field_multi1 = -x_percent_multipler; + right_center_gizmo->x_field_multi1 = x_percent_multipler; + rotate_gizmo->x_field_multi1 = x_percent_multipler; } } void TransformEffect::toggle_uniform_scale(bool enabled) { scale_y->set_enabled(!enabled); - top_center_gizmo->y_field = enabled ? scale_x : scale_y; - bottom_center_gizmo->y_field = enabled ? scale_x : scale_y; - top_left_gizmo->y_field = enabled ? NULL : scale_y; - top_right_gizmo->y_field = enabled ? NULL : scale_y; - bottom_left_gizmo->y_field = enabled ? NULL : scale_y; - bottom_right_gizmo->y_field = enabled ? NULL : scale_y; + top_center_gizmo->y_field1 = enabled ? scale_x : scale_y; + bottom_center_gizmo->y_field1 = enabled ? scale_x : scale_y; + top_left_gizmo->y_field1 = enabled ? NULL : scale_y; + top_right_gizmo->y_field1 = enabled ? NULL : scale_y; + bottom_left_gizmo->y_field1 = enabled ? NULL : scale_y; + bottom_right_gizmo->y_field1 = enabled ? NULL : scale_y; } void TransformEffect::process_coords(double timecode, GLTextureCoords& coords, int data) { diff --git a/io/loadthread.cpp b/io/loadthread.cpp index d35d3e791..90c10ac4f 100644 --- a/io/loadthread.cpp +++ b/io/loadthread.cpp @@ -1,4 +1,4 @@ -#include "loadthread.h" +#include "loadthread.h" #include "mainwindow.h" #include "panels/panels.h" @@ -28,9 +28,10 @@ struct TransitionData { Clip* ctc; }; -LoadThread::LoadThread(LoadDialog* l, bool a) : ld(l), autorecovery(a) { +LoadThread::LoadThread(LoadDialog* l, bool a) : ld(l), autorecovery(a), cancelled(false) { connect(this, SIGNAL(finished()), this, SLOT(deleteLater())); connect(this, SIGNAL(success()), this, SLOT(success_func())); + connect(this, SIGNAL(start_create_effect_ui(QXmlStreamReader*, Clip*, int, const EffectMeta*, long, bool)), this, SLOT(create_effect_ui(QXmlStreamReader*, Clip*, int, const EffectMeta*, long, bool))); } const EffectMeta* get_meta_from_name(const QString& name, int type) { @@ -42,7 +43,7 @@ const EffectMeta* get_meta_from_name(const QString& name, int type) { return NULL; } -void load_effect(QXmlStreamReader& stream, Clip* c) { +void LoadThread::load_effect(QXmlStreamReader& stream, Clip* c) { int effect_id = -1; QString effect_name; bool effect_enabled = true; @@ -95,30 +96,47 @@ void load_effect(QXmlStreamReader& stream, Clip* c) { } else { QString tag = stream.name().toString(); - if (tag == "opening" || tag == "closing") { - // TODO replace NULL/s with something else - - int transition_index = create_transition(c, NULL, meta); - Transition* t = c->sequence->transitions.at(transition_index); - if (effect_length > -1) t->set_length(effect_length); - t->set_enabled(effect_enabled); - t->load(stream); - - if (tag == "opening") { - c->opening_transition = transition_index; - } else { - c->closing_transition = transition_index; - } + int type; + if (tag == "opening") { + type = TA_OPENING_TRANSITION; + } else if (tag == "closing") { + type = TA_CLOSING_TRANSITION; } else { - Effect* e = create_effect(c, meta); - e->set_enabled(effect_enabled); - e->load(stream); - - c->effects.append(e); + type = TA_NO_TRANSITION; } + + emit start_create_effect_ui(&stream, c, type, meta, effect_length, effect_enabled); + + waitCond.wait(&mutex); } } +void LoadThread::read_next(QXmlStreamReader &stream) { + stream.readNext(); + update_current_element_count(stream); +} + +void LoadThread::read_next_start_element(QXmlStreamReader &stream) { + stream.readNextStartElement(); + update_current_element_count(stream); +} + +void LoadThread::update_current_element_count(QXmlStreamReader &stream) { + if (is_element(stream)) { + current_element_count++; + report_progress((current_element_count * 100) / total_element_count); + } +} + +bool LoadThread::is_element(QXmlStreamReader &stream) { + return stream.isStartElement() + && (stream.name() == "folder" + || stream.name() == "footage" + || stream.name() == "sequence" + || stream.name() == "clip" + || stream.name() == "effect"); +} + bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) { f.seek(0); stream.setDevice(stream.device()); @@ -149,8 +167,8 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) { show_err = true; - while (!stream.atEnd()) { - stream.readNextStartElement(); + while (!stream.atEnd() && !cancelled) { + read_next_start_element(stream); if (stream.name() == root_search) { if (type == LOAD_TYPE_VERSION) { int proj_version = stream.readElementText().toInt(); @@ -164,8 +182,8 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) { internal_proj_url = stream.readElementText(); internal_proj_dir = QFileInfo(internal_proj_url).absoluteDir(); } else { - while (!(stream.name() == root_search && stream.isEndElement())) { - stream.readNext(); + while (!cancelled && !(stream.name() == root_search && stream.isEndElement())) { + read_next(stream); if (stream.name() == child_search && stream.isStartElement()) { switch (type) { case MEDIA_TYPE_FOLDER: @@ -283,8 +301,8 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) { QVector transition_data; // load all clips and clip information - while (!(stream.name() == child_search && stream.isEndElement()) && !stream.atEnd()) { - stream.readNextStartElement(); + while (!cancelled && !(stream.name() == child_search && stream.isEndElement()) && !stream.atEnd()) { + read_next_start_element(stream); if (stream.name() == "marker" && stream.isStartElement()) { Marker m; for (int j=0;jclips.append(c); } } + if (cancelled) return false; // correct links, clip IDs, transitions for (int i=0;iclips.size();i++) { @@ -486,11 +507,12 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) { } } } + if (cancelled) return false; } break; } } - return true; + return !cancelled; } Media* LoadThread::find_loaded_folder_by_id(int id) { @@ -505,6 +527,8 @@ Media* LoadThread::find_loaded_folder_by_id(int id) { } void LoadThread::run() { + mutex.lock(); + QFile file(project_url); if (!file.open(QIODevice::ReadOnly)) { dout << "[ERROR] Could not open file"; @@ -534,17 +558,15 @@ void LoadThread::run() { loaded_sequences.clear(); // get "element" count - int element_count = 0; - while (!stream.atEnd()) { + current_element_count = 0; + total_element_count = 0; + while (!cancelled && !stream.atEnd()) { stream.readNextStartElement(); - if (stream.name() == "folder" - || stream.name() == "footage" - || stream.name() == "sequence" - || stream.name() == "clip" - || stream.name() == "effect") { - element_count++; + if (is_element(stream)) { + total_element_count++; } } + cont = !cancelled; // find project file version cont = load_worker(file, stream, LOAD_TYPE_VERSION); @@ -590,43 +612,105 @@ void LoadThread::run() { cont = load_worker(file, stream, MEDIA_TYPE_SEQUENCE); } - // attach nested sequence clips to their sequences - for (int i=0;imedia == NULL && loaded_clips.at(i)->media_stream == loaded_sequences.at(j)->to_sequence()->save_id) { - loaded_clips.at(i)->media = loaded_sequences.at(j); - loaded_clips.at(i)->refresh(); - break; + if (!cancelled) { + if (!cont) { + if (show_err) QMessageBox::critical(mainWindow, "Project Load Error", "Error loading project: " + error_str, QMessageBox::Ok); + } else if (stream.hasError()) { + dout << "[ERROR] Error parsing XML." << stream.errorString(); + QMessageBox::critical(mainWindow, "XML Parsing Error", "Couldn't load '" + project_url + "'. " + stream.errorString(), QMessageBox::Ok); + cont = false; + } else { + // attach nested sequence clips to their sequences + for (int i=0;imedia == NULL && loaded_clips.at(i)->media_stream == loaded_sequences.at(j)->to_sequence()->save_id) { + loaded_clips.at(i)->media = loaded_sequences.at(j); + loaded_clips.at(i)->refresh(); + break; + } + } } } } - if (!cont) { - if (show_err) QMessageBox::critical(mainWindow, "Project Load Error", "Error loading project: " + error_str, QMessageBox::Ok); - } else if (stream.hasError()) { - dout << "[ERROR] Error parsing XML." << stream.errorString(); - QMessageBox::critical(mainWindow, "XML Parsing Error", "Couldn't load '" + project_url + "'. " + stream.errorString(), QMessageBox::Ok); - cont = false; - } - if (cont) { mainWindow->setWindowModified(autorecovery); + panel_project->add_recent_project(project_url); + emit success(); // run in main thread for (int i=0;istart_preview_generator(loaded_media_items.at(i), true); } } else { - panel_project->new_project(); + mainWindow->new_project(); } - panel_project->add_recent_project(project_url); - file.close(); + + mutex.unlock(); +} + +void LoadThread::cancel() { + waitCond.wakeAll(); + cancelled = true; } void LoadThread::success_func() { if (open_seq != NULL) set_sequence(open_seq); update_ui(false); } + +void LoadThread::create_effect_ui( + QXmlStreamReader* stream, + Clip* c, + int type, + const EffectMeta* meta, + long effect_length, + bool effect_enabled) +{ + /* This is extremely hacky - prepare yourself. + * + * When moving project loading to a separate thread, it was soon discovered + * that effects wouldn't load correctly anymore. They were actually still + * "functional", but there were no controls appearing in EffectControls. + * + * Turns out since Effect creates its UI in its constructor, the UI was + * created in this thread rather than the main GUI thread, which is a big + * no-no. Unfortunately the design of Effect does not separate UI and data, + * so having the UI set up was integral to creating annd loading the effect. + * + * Therefore, rather than rewrite the class (I just rewrote QTreeWidget to + * QTreeView with a custom model/item so I'm exhausted), for + * quick-n-dirty-ness, I made LoadThread offload the effect creation to the + * main thread (and since the effect loads data from the same XML stream, + * the LoadThread has to wait for the effect to finish before it can + * continue. + * + * Sorry. I'll fix it one day. + */ + + if (cancelled) return; + if (type == TA_NO_TRANSITION) { + Effect* e = create_effect(c, meta); + e->set_enabled(effect_enabled); + e->load(*stream); + + c->effects.append(e); + } else { + int transition_index = create_transition(c, NULL, meta); + Transition* t = c->sequence->transitions.at(transition_index); + if (effect_length > -1) t->set_length(effect_length); + t->set_enabled(effect_enabled); + t->load(*stream); + + if (type == TA_OPENING_TRANSITION) { + c->opening_transition = transition_index; + } else { + c->closing_transition = transition_index; + } + } + waitCond.wakeAll(); + +} diff --git a/io/loadthread.h b/io/loadthread.h index 77bd0ca5f..b41123775 100644 --- a/io/loadthread.h +++ b/io/loadthread.h @@ -4,12 +4,15 @@ #include #include #include +#include +#include class Media; class Footage; class Clip; class Sequence; class LoadDialog; +class EffectMeta; class LoadThread : public QThread { @@ -17,15 +20,25 @@ class LoadThread : public QThread public: LoadThread(LoadDialog* l, bool a); void run(); + void cancel(); signals: void success(); + void start_create_effect_ui(QXmlStreamReader* stream, Clip* c, int type, const EffectMeta* meta, long effect_length, bool effect_enabled); + void report_progress(int p); private slots: void success_func(); + void create_effect_ui(QXmlStreamReader* stream, Clip* c, int type, const EffectMeta* meta, long effect_length, bool effect_enabled); private: LoadDialog* ld; bool autorecovery; bool load_worker(QFile& f, QXmlStreamReader& stream, int type); + void load_effect(QXmlStreamReader& stream, Clip* c); + + void read_next(QXmlStreamReader& stream); + void read_next_start_element(QXmlStreamReader& stream); + void update_current_element_count(QXmlStreamReader& stream); + Sequence* open_seq; QVector loaded_media_items; QDir proj_dir; @@ -34,10 +47,20 @@ private: bool show_err; QString error_str; + bool is_element(QXmlStreamReader& stream); + QVector loaded_folders; QVector loaded_clips; QVector loaded_sequences; Media* find_loaded_folder_by_id(int id); + + int current_element_count; + int total_element_count; + + QMutex mutex; + QWaitCondition waitCond; + + bool cancelled; }; #endif // LOADTHREAD_H diff --git a/io/previewgenerator.cpp b/io/previewgenerator.cpp index 83fc426e6..5b9cc097b 100644 --- a/io/previewgenerator.cpp +++ b/io/previewgenerator.cpp @@ -127,7 +127,7 @@ bool PreviewGenerator::retrieve_preview(const QString& hash) { QString thumb_path = get_thumbnail_path(hash, ms); QFile f(thumb_path); if (f.exists() && ms->video_preview.load(thumb_path)) { - dout << "loaded thumb" << ms->file_index << "from" << thumb_path; + //dout << "loaded thumb" << ms->file_index << "from" << thumb_path; ms->preview_done = true; } else { found = false; @@ -139,7 +139,7 @@ bool PreviewGenerator::retrieve_preview(const QString& hash) { QString waveform_path = get_waveform_path(hash, ms); QFile f(waveform_path); if (f.exists()) { - dout << "loaded wave" << ms->file_index << "from" << waveform_path; + //dout << "loaded wave" << ms->file_index << "from" << waveform_path; f.open(QFile::ReadOnly); QByteArray data = f.readAll(); ms->audio_preview.resize(data.size()); @@ -433,7 +433,7 @@ void PreviewGenerator::run() { // see if we already have data for this QFileInfo file_info(footage->url); QString cache_file = footage->url.mid(footage->url.lastIndexOf('/')+1) + QString::number(file_info.size()) + QString::number(file_info.lastModified().toMSecsSinceEpoch()); - dout << "using hash" << cache_file; + //dout << "using hash" << cache_file; QString hash = QCryptographicHash::hash(cache_file.toLatin1(), QCryptographicHash::Md5).toHex(); if (retrieve_preview(hash)) { @@ -445,7 +445,7 @@ void PreviewGenerator::run() { for (int i=0;ivideo_tracks.size();i++) { FootageStream* ms = footage->video_tracks.at(i); ms->video_preview.save(get_thumbnail_path(hash, ms), "PNG"); - dout << "saved" << ms->file_index << "thumbnail to" << get_thumbnail_path(hash, ms); + //dout << "saved" << ms->file_index << "thumbnail to" << get_thumbnail_path(hash, ms); } for (int i=0;iaudio_tracks.size();i++) { FootageStream* ms = footage->audio_tracks.at(i); @@ -453,7 +453,7 @@ void PreviewGenerator::run() { f.open(QFile::WriteOnly); f.write(ms->audio_preview.constData(), ms->audio_preview.size()); f.close(); - dout << "saved" << ms->file_index << "waveform to" << get_waveform_path(hash, ms); + //dout << "saved" << ms->file_index << "waveform to" << get_waveform_path(hash, ms); } sem.release(); diff --git a/mainwindow.cpp b/mainwindow.cpp index ce8bcbd43..3b38c9dee 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -220,6 +220,7 @@ MainWindow::MainWindow(QWidget *parent) : connect(ui->actionCu_t, SIGNAL(triggered(bool)), this, SLOT(cut())); connect(ui->actionCop_y, SIGNAL(triggered(bool)), this, SLOT(copy())); connect(ui->action_Paste, SIGNAL(triggered(bool)), this, SLOT(paste())); + connect(ui->actionProject, SIGNAL(triggered(bool)), this, SLOT(new_project())); } MainWindow::~MainWindow() { @@ -418,7 +419,19 @@ void MainWindow::copy() { void MainWindow::paste() { if ((panel_timeline->focused() || panel_effect_controls->is_focused()) && sequence != NULL) { panel_timeline->paste(false); - } + } +} + +void MainWindow::new_project() { + if (can_close_project()) { + panel_effect_controls->clear_effects(true); + undo_stack.clear(); + project_url.clear(); + panel_project->new_project(); + updateTitle(""); + update_ui(false); + panel_project->source_table->update(); + } } void MainWindow::on_actionSplit_at_Playhead_triggered() @@ -516,18 +529,6 @@ void MainWindow::on_action_Open_Project_triggered() } } -void MainWindow::on_actionProject_triggered() -{ - if (can_close_project()) { - panel_effect_controls->clear_effects(true); - undo_stack.clear(); - project_url.clear(); - panel_project->new_project(); - updateTitle(""); - update_ui(false); - } -} - void MainWindow::on_actionSave_Project_As_triggered() { save_project_as(); diff --git a/mainwindow.h b/mainwindow.h index 18e2fd455..c2dd7bfb7 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -28,6 +28,7 @@ public slots: void cut(); void copy(); void paste(); + void new_project(); void autorecover_interval(); void on_actionNest_triggered(); @@ -70,8 +71,6 @@ private slots: void on_action_Open_Project_triggered(); - void on_actionProject_triggered(); - void on_actionSave_Project_As_triggered(); void on_actionDeselect_All_triggered(); diff --git a/panels/project.cpp b/panels/project.cpp index d4a66e715..6b77d01a0 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -62,11 +62,7 @@ Project::Project(QWidget *parent) : sorter = new QSortFilterProxyModel(this); sorter->setSourceModel(&project_model); - source_table->setModel(sorter); - - /*Media* m = new Media(project_model.get_root()); - project_model.get_root()->appendChild(m);*/ } Project::~Project() { @@ -738,7 +734,6 @@ void Project::new_project() { set_sequence(NULL); panel_footage_viewer->set_media(NULL); clear(); - panel_project->source_table->update(); mainWindow->setWindowModified(false); } @@ -1038,7 +1033,7 @@ void MediaThrobber::animation_update() { if (animation == THROBBER_LIMIT) { animation = 0; } - item->set_icon(QIcon(pixmap.copy(THROBBER_SIZE*animation, 0, THROBBER_SIZE, THROBBER_SIZE))); + project_model.set_icon(item, QIcon(pixmap.copy(THROBBER_SIZE*animation, 0, THROBBER_SIZE, THROBBER_SIZE))); animation++; } @@ -1049,10 +1044,10 @@ void MediaThrobber::stop(int icon_type, bool replace) { } switch (icon_type) { - case ICON_TYPE_VIDEO: item->set_icon(QIcon(":/icons/videosource.png")); break; - case ICON_TYPE_AUDIO: item->set_icon(QIcon(":/icons/audiosource.png")); break; - case ICON_TYPE_IMAGE: item->set_icon(QIcon(":/icons/imagesource.png")); break; - case ICON_TYPE_ERROR: item->set_icon(QIcon(":/icons/error.png")); break; + case ICON_TYPE_VIDEO: project_model.set_icon(item, QIcon(":/icons/videosource.png")); break; + case ICON_TYPE_AUDIO: project_model.set_icon(item, QIcon(":/icons/audiosource.png")); break; + case ICON_TYPE_IMAGE: project_model.set_icon(item, QIcon(":/icons/imagesource.png")); break; + case ICON_TYPE_ERROR: project_model.set_icon(item, QIcon(":/icons/error.png")); break; } // refresh all clips diff --git a/project/effect.cpp b/project/effect.cpp index 3358e4822..7d9d25e0f 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -868,13 +868,21 @@ void Effect::gizmo_move(EffectGizmo* gizmo, int x_movement, int y_movement, doub if (gizmos.at(i) == gizmo) { ComboAction* ca = NULL; if (done) ca = new ComboAction(); - if (gizmo->x_field != NULL) { - gizmo->x_field->set_double_value(gizmo->x_field->get_double_value(timecode) + x_movement*gizmo->x_field_multi); - gizmo->x_field->make_key_from_change(ca); + if (gizmo->x_field1 != NULL) { + gizmo->x_field1->set_double_value(gizmo->x_field1->get_double_value(timecode) + x_movement*gizmo->x_field_multi1); + gizmo->x_field1->make_key_from_change(ca); } - if (gizmo->y_field != NULL) { - gizmo->y_field->set_double_value(gizmo->y_field->get_double_value(timecode) + y_movement*gizmo->y_field_multi); - gizmo->y_field->make_key_from_change(ca); + if (gizmo->y_field1 != NULL) { + gizmo->y_field1->set_double_value(gizmo->y_field1->get_double_value(timecode) + y_movement*gizmo->y_field_multi1); + gizmo->y_field1->make_key_from_change(ca); + } + if (gizmo->x_field2 != NULL) { + gizmo->x_field2->set_double_value(gizmo->x_field2->get_double_value(timecode) + x_movement*gizmo->x_field_multi2); + gizmo->x_field2->make_key_from_change(ca); + } + if (gizmo->y_field2 != NULL) { + gizmo->y_field2->set_double_value(gizmo->y_field2->get_double_value(timecode) + y_movement*gizmo->y_field_multi2); + gizmo->y_field2->make_key_from_change(ca); } if (done) undo_stack.push(ca); break; diff --git a/project/effectgizmo.cpp b/project/effectgizmo.cpp index 0eecbac8f..65bf0cc31 100644 --- a/project/effectgizmo.cpp +++ b/project/effectgizmo.cpp @@ -4,10 +4,14 @@ #include "effectfield.h" EffectGizmo::EffectGizmo(int type) : - x_field(NULL), - x_field_multi(1.0), - y_field(NULL), - y_field_multi(1.0), + x_field1(NULL), + x_field_multi1(1.0), + y_field1(NULL), + y_field_multi1(1.0), + x_field2(NULL), + x_field_multi2(1.0), + y_field2(NULL), + y_field_multi2(1.0), type(type), cursor(-1) { @@ -19,8 +23,10 @@ EffectGizmo::EffectGizmo(int type) : } void EffectGizmo::set_previous_value() { - if (x_field != NULL) static_cast(x_field->ui_element)->set_previous_value(); - if (y_field != NULL) static_cast(y_field->ui_element)->set_previous_value(); + if (x_field1 != NULL) static_cast(x_field1->ui_element)->set_previous_value(); + if (y_field1 != NULL) static_cast(y_field1->ui_element)->set_previous_value(); + if (x_field2 != NULL) static_cast(x_field2->ui_element)->set_previous_value(); + if (y_field2 != NULL) static_cast(y_field2->ui_element)->set_previous_value(); } int EffectGizmo::get_point_count() { diff --git a/project/effectgizmo.h b/project/effectgizmo.h index ec10f4b09..127e0ed14 100644 --- a/project/effectgizmo.h +++ b/project/effectgizmo.h @@ -24,10 +24,14 @@ public: QVector world_pos; QVector screen_pos; - EffectField* x_field; - double x_field_multi; - EffectField* y_field; - double y_field_multi; + EffectField* x_field1; + double x_field_multi1; + EffectField* y_field1; + double y_field_multi1; + EffectField* x_field2; + double x_field_multi2; + EffectField* y_field2; + double y_field_multi2; void set_previous_value(); diff --git a/project/projectmodel.cpp b/project/projectmodel.cpp index 358c443a7..74b284cb6 100644 --- a/project/projectmodel.cpp +++ b/project/projectmodel.cpp @@ -19,15 +19,13 @@ void ProjectModel::destroy_root() { if (panel_footage_viewer != NULL) panel_footage_viewer->viewer_widget->delete_function(); if (root_item != NULL) { - beginRemoveRows(QModelIndex(), 0, root_item->childCount()); delete root_item; - endRemoveRows(); } } void ProjectModel::clear() { - destroy_root(); beginResetModel(); + destroy_root(); root_item = new Media(0); root_item->root = true; endResetModel(); @@ -132,6 +130,13 @@ Media *ProjectModel::getItem(const QModelIndex &index) const { return root_item; } +void ProjectModel::set_icon(Media* m, const QIcon &ico) { + QModelIndex index = createIndex(m->row(), 0, m); + m->set_icon(ico); + emit dataChanged(index, index); + +} + void ProjectModel::appendChild(Media *parent, Media *child) { if (parent == NULL) parent = root_item; beginInsertRows(parent == root_item ? QModelIndex() : createIndex(parent->row(), 0, parent), parent->childCount(), parent->childCount()); diff --git a/project/projectmodel.h b/project/projectmodel.h index e5d6b9a87..42709b848 100644 --- a/project/projectmodel.h +++ b/project/projectmodel.h @@ -32,6 +32,7 @@ public: void removeChild(Media *parent, Media* m); Media *child(int i, Media* parent = NULL); int childCount(Media* parent = NULL); + void set_icon(Media* m, const QIcon &ico); private: Media* root_item;