From 928adde78a36eeab020bb52a613ee0dad814cc54 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Wed, 13 Mar 2019 00:22:19 +1100 Subject: [PATCH] removed main thread pass-off when loading --- io/loadthread.cpp | 130 +++++++++++++++++----------------------------- io/loadthread.h | 16 +----- 2 files changed, 49 insertions(+), 97 deletions(-) diff --git a/io/loadthread.cpp b/io/loadthread.cpp index 5aab007ea..891b930aa 100644 --- a/io/loadthread.cpp +++ b/io/loadthread.cpp @@ -47,11 +47,6 @@ LoadThread::LoadThread(const QString& filename, bool autorecovery, bool clear) : connect(this, SIGNAL(success()), this, SLOT(success_func()), Qt::QueuedConnection); connect(this, SIGNAL(error()), this, SLOT(error_func()), Qt::QueuedConnection); - connect(this, - SIGNAL(start_create_effect_ui(QXmlStreamReader*, Clip*, int, const QString*, const EffectMeta*, long, bool)), - this, - SLOT(create_effect_ui(QXmlStreamReader*, Clip*, int, const QString*, const EffectMeta*, long, bool)), - Qt::QueuedConnection); connect(this, SIGNAL(start_question(const QString&, const QString &, int)), this, @@ -135,9 +130,34 @@ void LoadThread::load_effect(QXmlStreamReader& stream, Clip* c) { type = kTransitionNone; } - // effect UI creation has to occur in the main thread, see an explanation in create_effect_ui() - emit start_create_effect_ui(&stream, c, type, &effect_name, meta, effect_length, effect_enabled); - waitCond.wait(&mutex); + // effect construction + if (cancelled_) return; + if (type == kTransitionNone) { + if (meta == nullptr) { + // create void effect + EffectPtr ve(new VoidEffect(c, effect_name)); + ve->SetEnabled(effect_enabled); + ve->load(stream); + c->effects.append(ve); + } else { + EffectPtr e(Effect::Create(c, meta)); + e->SetEnabled(effect_enabled); + e->load(stream); + + c->effects.append(e); + } + } else { + TransitionPtr t = Transition::Create(c, nullptr, meta); + if (effect_length > -1) t->set_length(effect_length); + t->SetEnabled(effect_enabled); + t->load(stream); + + if (type == kTransitionOpening) { + c->opening_transition = t; + } else { + c->closing_transition = t; + } + } } void LoadThread::read_next(QXmlStreamReader &stream) { @@ -157,6 +177,16 @@ void LoadThread::update_current_element_count(QXmlStreamReader &stream) { } } +void LoadThread::show_message(const QString& title, const QString& body, int buttons) +{ + emit start_question( + title, + body, + buttons + ); + waitCond.wait(&mutex); +} + bool LoadThread::is_element(QXmlStreamReader &stream) { return stream.isStartElement() && (stream.name() == "folder" @@ -204,12 +234,11 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) { if (type == LOAD_TYPE_VERSION) { proj_version = stream.readElementText().toInt(); if (proj_version < olive::kMinimumSaveVersion || proj_version > olive::kSaveVersion) { - emit start_question( - tr("Version Mismatch"), - tr("This project was saved in a different version of Olive and may not be fully compatible with this version. Would you like to attempt loading it anyway?"), - QMessageBox::Yes | QMessageBox::No + show_message( + tr("Version Mismatch"), + tr("This project was saved in a different version of Olive and may not be fully compatible with this version. Would you like to attempt loading it anyway?"), + QMessageBox::Yes | QMessageBox::No ); - waitCond.wait(&mutex); if (question_btn == QMessageBox::No) { show_err = false; return false; @@ -398,7 +427,8 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) { s->markers.append(m); } else if (stream.name() == "clip" && stream.isStartElement()) { int media_type = -1; - int media_id, stream_id; + int media_id = -1; + int stream_id = -1; ClipPtr c = std::make_shared(s.get()); @@ -455,7 +485,7 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) { // set media and media stream switch (media_type) { case MEDIA_TYPE_FOOTAGE: - if (media_id >= 0) { + if (media_id >= 0 && stream_id >= 0) { for (int j=0;jto_footage(); if (m->save_id == media_id) { @@ -528,12 +558,12 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) { correct_clip->linked.removeAt(j); j--; - emit start_question( + show_message( tr("Invalid Clip Link"), tr("This project contains an invalid clip link. It may be corrupt. Would you like to continue loading it?"), QMessageBox::Yes | QMessageBox::No ); - waitCond.wait(&mutex); + if (question_btn == QMessageBox::No) { s.reset(); return false; @@ -745,69 +775,3 @@ void LoadThread::success_func() { olive::Global->set_sequence(open_seq); } } - -void LoadThread::create_effect_ui( - QXmlStreamReader* stream, - Clip* c, - int type, - const QString* effect_name, - 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. - */ - - // lock mutex - ensures the load thread is suspended while this happens - mutex.lock(); - - if (cancelled_) return; - if (type == kTransitionNone) { - if (meta == nullptr) { - // create void effect - EffectPtr ve(new VoidEffect(c, *effect_name)); - ve->SetEnabled(effect_enabled); - ve->load(*stream); - c->effects.append(ve); - } else { - EffectPtr e(Effect::Create(c, meta)); - e->SetEnabled(effect_enabled); - e->load(*stream); - - c->effects.append(e); - } - } else { - TransitionPtr t = Transition::Create(c, nullptr, meta); - if (effect_length > -1) t->set_length(effect_length); - t->SetEnabled(effect_enabled); - t->load(*stream); - - if (type == kTransitionOpening) { - c->opening_transition = t; - } else { - c->closing_transition = t; - } - } - - mutex.unlock(); - - waitCond.wakeAll(); -} diff --git a/io/loadthread.h b/io/loadthread.h index 14b92e7b2..22da99ded 100644 --- a/io/loadthread.h +++ b/io/loadthread.h @@ -41,25 +41,11 @@ signals: void start_question(const QString &title, const QString &text, int buttons); void success(); void error(); - void start_create_effect_ui(QXmlStreamReader* stream, - Clip* c, - int type, - const QString *effect_name, - const EffectMeta* meta, - long effect_length, - bool effect_enabled); void report_progress(int p); private slots: void question_func(const QString &title, const QString &text, int buttons); void error_func(); void success_func(); - void create_effect_ui(QXmlStreamReader* stream, - Clip* c, - int type, - const QString *effect_name, - const EffectMeta* meta, - long effect_length, - bool effect_enabled); private: bool autorecovery_; bool clear_; @@ -72,6 +58,8 @@ private: void read_next_start_element(QXmlStreamReader& stream); void update_current_element_count(QXmlStreamReader& stream); + void show_message(const QString& title, const QString& body, int buttons); + SequencePtr open_seq; QVector loaded_media_items; QDir proj_dir;