removed main thread pass-off when loading

This commit is contained in:
itsmattkc
2019-03-13 00:22:19 +11:00
parent e3e45279b9
commit 928adde78a
2 changed files with 49 additions and 97 deletions
+47 -83
View File
@@ -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<Clip>(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;j<loaded_media_items.size();j++) {
Footage* m = loaded_media_items.at(j)->to_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();
}