vastly improved multithreaded loading and annchor point gizmo
This commit is contained in:
+13
-5
@@ -11,6 +11,7 @@
|
|||||||
#include "io/loadthread.h"
|
#include "io/loadthread.h"
|
||||||
#include "playback/playback.h"
|
#include "playback/playback.h"
|
||||||
#include "ui/sourcetable.h"
|
#include "ui/sourcetable.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
|
||||||
LoadDialog::LoadDialog(QWidget *parent, bool autorecovery) : QDialog(parent) {
|
LoadDialog::LoadDialog(QWidget *parent, bool autorecovery) : QDialog(parent) {
|
||||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
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) + "'..."));
|
layout->addWidget(new QLabel("Loading '" + project_url.mid(project_url.lastIndexOf('/')+1) + "'..."));
|
||||||
|
|
||||||
bar = new QProgressBar();
|
bar = new QProgressBar();
|
||||||
bar->setValue(50);
|
bar->setValue(0);
|
||||||
layout->addWidget(bar);
|
layout->addWidget(bar);
|
||||||
|
|
||||||
cancel_button = new QPushButton("Cancel");
|
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 = new QHBoxLayout();
|
||||||
hboxLayout->addStretch();
|
hboxLayout->addStretch();
|
||||||
@@ -36,12 +37,19 @@ LoadDialog::LoadDialog(QWidget *parent, bool autorecovery) : QDialog(parent) {
|
|||||||
|
|
||||||
update();
|
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(success()), this, SLOT(thread_done()));
|
||||||
|
QObject::connect(lt, SIGNAL(report_progress(int)), bar, SLOT(setValue(int)));
|
||||||
lt->start();
|
lt->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoadDialog::cancel() {
|
||||||
|
lt->cancel();
|
||||||
|
lt->wait();
|
||||||
|
mainWindow->new_project();
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
|
||||||
void LoadDialog::thread_done() {
|
void LoadDialog::thread_done() {
|
||||||
// project_model.update_data();
|
accept();
|
||||||
close();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ class Sequence;
|
|||||||
class Media;
|
class Media;
|
||||||
class Footage;
|
class Footage;
|
||||||
class QHBoxLayout;
|
class QHBoxLayout;
|
||||||
|
class LoadThread;
|
||||||
|
|
||||||
class LoadDialog : public QDialog
|
class LoadDialog : public QDialog
|
||||||
{
|
{
|
||||||
@@ -15,11 +16,13 @@ class LoadDialog : public QDialog
|
|||||||
public:
|
public:
|
||||||
LoadDialog(QWidget* parent, bool autorecovery);
|
LoadDialog(QWidget* parent, bool autorecovery);
|
||||||
private slots:
|
private slots:
|
||||||
|
void cancel();
|
||||||
void thread_done();
|
void thread_done();
|
||||||
private:
|
private:
|
||||||
QProgressBar* bar;
|
QProgressBar* bar;
|
||||||
QPushButton* cancel_button;
|
QPushButton* cancel_button;
|
||||||
QHBoxLayout* hboxLayout;
|
QHBoxLayout* hboxLayout;
|
||||||
|
LoadThread* lt;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LOADDIALOG_H
|
#endif // LOADDIALOG_H
|
||||||
|
|||||||
@@ -28,20 +28,20 @@ CornerPinEffect::CornerPinEffect(Clip *c, const EffectMeta *em) : Effect(c, em)
|
|||||||
perspective->set_bool_value(true);
|
perspective->set_bool_value(true);
|
||||||
|
|
||||||
top_left_gizmo = add_gizmo(GIZMO_TYPE_DOT);
|
top_left_gizmo = add_gizmo(GIZMO_TYPE_DOT);
|
||||||
top_left_gizmo->x_field = top_left_x;
|
top_left_gizmo->x_field1 = top_left_x;
|
||||||
top_left_gizmo->y_field = top_left_y;
|
top_left_gizmo->y_field1 = top_left_y;
|
||||||
|
|
||||||
top_right_gizmo = add_gizmo(GIZMO_TYPE_DOT);
|
top_right_gizmo = add_gizmo(GIZMO_TYPE_DOT);
|
||||||
top_right_gizmo->x_field = top_right_x;
|
top_right_gizmo->x_field1 = top_right_x;
|
||||||
top_right_gizmo->y_field = top_right_y;
|
top_right_gizmo->y_field1 = top_right_y;
|
||||||
|
|
||||||
bottom_left_gizmo = add_gizmo(GIZMO_TYPE_DOT);
|
bottom_left_gizmo = add_gizmo(GIZMO_TYPE_DOT);
|
||||||
bottom_left_gizmo->x_field = bottom_left_x;
|
bottom_left_gizmo->x_field1 = bottom_left_x;
|
||||||
bottom_left_gizmo->y_field = bottom_left_y;
|
bottom_left_gizmo->y_field1 = bottom_left_y;
|
||||||
|
|
||||||
bottom_right_gizmo = add_gizmo(GIZMO_TYPE_DOT);
|
bottom_right_gizmo = add_gizmo(GIZMO_TYPE_DOT);
|
||||||
bottom_right_gizmo->x_field = bottom_right_x;
|
bottom_right_gizmo->x_field1 = bottom_right_x;
|
||||||
bottom_right_gizmo->y_field = bottom_right_y;
|
bottom_right_gizmo->y_field1 = bottom_right_y;
|
||||||
|
|
||||||
vertPath = "cornerpin.vert";
|
vertPath = "cornerpin.vert";
|
||||||
fragPath = "cornerpin.frag";
|
fragPath = "cornerpin.frag";
|
||||||
|
|||||||
@@ -68,49 +68,51 @@ TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em)
|
|||||||
// set up gizmos
|
// set up gizmos
|
||||||
top_left_gizmo = add_gizmo(GIZMO_TYPE_DOT);
|
top_left_gizmo = add_gizmo(GIZMO_TYPE_DOT);
|
||||||
top_left_gizmo->set_cursor(Qt::SizeFDiagCursor);
|
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 = add_gizmo(GIZMO_TYPE_DOT);
|
||||||
top_center_gizmo->set_cursor(Qt::SizeVerCursor);
|
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 = add_gizmo(GIZMO_TYPE_DOT);
|
||||||
top_right_gizmo->set_cursor(Qt::SizeBDiagCursor);
|
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 = add_gizmo(GIZMO_TYPE_DOT);
|
||||||
bottom_left_gizmo->set_cursor(Qt::SizeBDiagCursor);
|
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 = add_gizmo(GIZMO_TYPE_DOT);
|
||||||
bottom_center_gizmo->set_cursor(Qt::SizeVerCursor);
|
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 = add_gizmo(GIZMO_TYPE_DOT);
|
||||||
bottom_right_gizmo->set_cursor(Qt::SizeFDiagCursor);
|
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 = add_gizmo(GIZMO_TYPE_DOT);
|
||||||
left_center_gizmo->set_cursor(Qt::SizeHorCursor);
|
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 = add_gizmo(GIZMO_TYPE_DOT);
|
||||||
right_center_gizmo->set_cursor(Qt::SizeHorCursor);
|
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 = add_gizmo(GIZMO_TYPE_TARGET);
|
||||||
anchor_gizmo->set_cursor(Qt::SizeAllCursor);
|
anchor_gizmo->set_cursor(Qt::SizeAllCursor);
|
||||||
anchor_gizmo->x_field = anchor_x_box;
|
anchor_gizmo->x_field1 = anchor_x_box;
|
||||||
anchor_gizmo->y_field = anchor_y_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 = add_gizmo(GIZMO_TYPE_DOT);
|
||||||
rotate_gizmo->color = Qt::green;
|
rotate_gizmo->color = Qt::green;
|
||||||
rotate_gizmo->set_cursor(Qt::SizeAllCursor);
|
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 = add_gizmo(GIZMO_TYPE_POLY);
|
||||||
rect_gizmo->x_field = position_x;
|
rect_gizmo->x_field1 = position_x;
|
||||||
rect_gizmo->y_field = position_y;
|
rect_gizmo->y_field1 = position_y;
|
||||||
|
|
||||||
connect(uniform_scale_field, SIGNAL(toggled(bool)), this, SLOT(toggle_uniform_scale(bool)));
|
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 x_percent_multipler = 200.0 / parent_clip->sequence->width;
|
||||||
double y_percent_multipler = 200.0 / parent_clip->sequence->height;
|
double y_percent_multipler = 200.0 / parent_clip->sequence->height;
|
||||||
top_left_gizmo->x_field_multi = -x_percent_multipler;
|
top_left_gizmo->x_field_multi1 = -x_percent_multipler;
|
||||||
top_left_gizmo->y_field_multi = -y_percent_multipler;
|
top_left_gizmo->y_field_multi1 = -y_percent_multipler;
|
||||||
top_center_gizmo->y_field_multi = -y_percent_multipler;
|
top_center_gizmo->y_field_multi1 = -y_percent_multipler;
|
||||||
top_right_gizmo->x_field_multi = x_percent_multipler;
|
top_right_gizmo->x_field_multi1 = x_percent_multipler;
|
||||||
top_right_gizmo->y_field_multi = -y_percent_multipler;
|
top_right_gizmo->y_field_multi1 = -y_percent_multipler;
|
||||||
bottom_left_gizmo->x_field_multi = -x_percent_multipler;
|
bottom_left_gizmo->x_field_multi1 = -x_percent_multipler;
|
||||||
bottom_left_gizmo->y_field_multi = y_percent_multipler;
|
bottom_left_gizmo->y_field_multi1 = y_percent_multipler;
|
||||||
bottom_center_gizmo->y_field_multi = y_percent_multipler;
|
bottom_center_gizmo->y_field_multi1 = y_percent_multipler;
|
||||||
bottom_right_gizmo->x_field_multi = x_percent_multipler;
|
bottom_right_gizmo->x_field_multi1 = x_percent_multipler;
|
||||||
bottom_right_gizmo->y_field_multi = y_percent_multipler;
|
bottom_right_gizmo->y_field_multi1 = y_percent_multipler;
|
||||||
left_center_gizmo->x_field_multi = -x_percent_multipler;
|
left_center_gizmo->x_field_multi1 = -x_percent_multipler;
|
||||||
right_center_gizmo->x_field_multi = x_percent_multipler;
|
right_center_gizmo->x_field_multi1 = x_percent_multipler;
|
||||||
rotate_gizmo->x_field_multi = x_percent_multipler;
|
rotate_gizmo->x_field_multi1 = x_percent_multipler;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransformEffect::toggle_uniform_scale(bool enabled) {
|
void TransformEffect::toggle_uniform_scale(bool enabled) {
|
||||||
scale_y->set_enabled(!enabled);
|
scale_y->set_enabled(!enabled);
|
||||||
|
|
||||||
top_center_gizmo->y_field = enabled ? scale_x : scale_y;
|
top_center_gizmo->y_field1 = enabled ? scale_x : scale_y;
|
||||||
bottom_center_gizmo->y_field = enabled ? scale_x : scale_y;
|
bottom_center_gizmo->y_field1 = enabled ? scale_x : scale_y;
|
||||||
top_left_gizmo->y_field = enabled ? NULL : scale_y;
|
top_left_gizmo->y_field1 = enabled ? NULL : scale_y;
|
||||||
top_right_gizmo->y_field = enabled ? NULL : scale_y;
|
top_right_gizmo->y_field1 = enabled ? NULL : scale_y;
|
||||||
bottom_left_gizmo->y_field = enabled ? NULL : scale_y;
|
bottom_left_gizmo->y_field1 = enabled ? NULL : scale_y;
|
||||||
bottom_right_gizmo->y_field = enabled ? NULL : scale_y;
|
bottom_right_gizmo->y_field1 = enabled ? NULL : scale_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransformEffect::process_coords(double timecode, GLTextureCoords& coords, int data) {
|
void TransformEffect::process_coords(double timecode, GLTextureCoords& coords, int data) {
|
||||||
|
|||||||
+143
-59
@@ -1,4 +1,4 @@
|
|||||||
#include "loadthread.h"
|
#include "loadthread.h"
|
||||||
|
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "panels/panels.h"
|
#include "panels/panels.h"
|
||||||
@@ -28,9 +28,10 @@ struct TransitionData {
|
|||||||
Clip* ctc;
|
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(finished()), this, SLOT(deleteLater()));
|
||||||
connect(this, SIGNAL(success()), this, SLOT(success_func()));
|
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) {
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_effect(QXmlStreamReader& stream, Clip* c) {
|
void LoadThread::load_effect(QXmlStreamReader& stream, Clip* c) {
|
||||||
int effect_id = -1;
|
int effect_id = -1;
|
||||||
QString effect_name;
|
QString effect_name;
|
||||||
bool effect_enabled = true;
|
bool effect_enabled = true;
|
||||||
@@ -95,30 +96,47 @@ void load_effect(QXmlStreamReader& stream, Clip* c) {
|
|||||||
} else {
|
} else {
|
||||||
QString tag = stream.name().toString();
|
QString tag = stream.name().toString();
|
||||||
|
|
||||||
if (tag == "opening" || tag == "closing") {
|
int type;
|
||||||
// TODO replace NULL/s with something else
|
if (tag == "opening") {
|
||||||
|
type = TA_OPENING_TRANSITION;
|
||||||
int transition_index = create_transition(c, NULL, meta);
|
} else if (tag == "closing") {
|
||||||
Transition* t = c->sequence->transitions.at(transition_index);
|
type = TA_CLOSING_TRANSITION;
|
||||||
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;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Effect* e = create_effect(c, meta);
|
type = TA_NO_TRANSITION;
|
||||||
e->set_enabled(effect_enabled);
|
|
||||||
e->load(stream);
|
|
||||||
|
|
||||||
c->effects.append(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
||||||
f.seek(0);
|
f.seek(0);
|
||||||
stream.setDevice(stream.device());
|
stream.setDevice(stream.device());
|
||||||
@@ -149,8 +167,8 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
|||||||
|
|
||||||
show_err = true;
|
show_err = true;
|
||||||
|
|
||||||
while (!stream.atEnd()) {
|
while (!stream.atEnd() && !cancelled) {
|
||||||
stream.readNextStartElement();
|
read_next_start_element(stream);
|
||||||
if (stream.name() == root_search) {
|
if (stream.name() == root_search) {
|
||||||
if (type == LOAD_TYPE_VERSION) {
|
if (type == LOAD_TYPE_VERSION) {
|
||||||
int proj_version = stream.readElementText().toInt();
|
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_url = stream.readElementText();
|
||||||
internal_proj_dir = QFileInfo(internal_proj_url).absoluteDir();
|
internal_proj_dir = QFileInfo(internal_proj_url).absoluteDir();
|
||||||
} else {
|
} else {
|
||||||
while (!(stream.name() == root_search && stream.isEndElement())) {
|
while (!cancelled && !(stream.name() == root_search && stream.isEndElement())) {
|
||||||
stream.readNext();
|
read_next(stream);
|
||||||
if (stream.name() == child_search && stream.isStartElement()) {
|
if (stream.name() == child_search && stream.isStartElement()) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case MEDIA_TYPE_FOLDER:
|
case MEDIA_TYPE_FOLDER:
|
||||||
@@ -283,8 +301,8 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
|||||||
QVector<TransitionData> transition_data;
|
QVector<TransitionData> transition_data;
|
||||||
|
|
||||||
// load all clips and clip information
|
// load all clips and clip information
|
||||||
while (!(stream.name() == child_search && stream.isEndElement()) && !stream.atEnd()) {
|
while (!cancelled && !(stream.name() == child_search && stream.isEndElement()) && !stream.atEnd()) {
|
||||||
stream.readNextStartElement();
|
read_next_start_element(stream);
|
||||||
if (stream.name() == "marker" && stream.isStartElement()) {
|
if (stream.name() == "marker" && stream.isStartElement()) {
|
||||||
Marker m;
|
Marker m;
|
||||||
for (int j=0;j<stream.attributes().size();j++) {
|
for (int j=0;j<stream.attributes().size();j++) {
|
||||||
@@ -387,12 +405,12 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load links and effects
|
// load links and effects
|
||||||
while (!(stream.name() == "clip" && stream.isEndElement()) && !stream.atEnd()) {
|
while (!cancelled && !(stream.name() == "clip" && stream.isEndElement()) && !stream.atEnd()) {
|
||||||
stream.readNext();
|
read_next(stream);
|
||||||
if (stream.isStartElement()) {
|
if (stream.isStartElement()) {
|
||||||
if (stream.name() == "linked") {
|
if (stream.name() == "linked") {
|
||||||
while (!(stream.name() == "linked" && stream.isEndElement()) && !stream.atEnd()) {
|
while (!cancelled && !(stream.name() == "linked" && stream.isEndElement()) && !stream.atEnd()) {
|
||||||
stream.readNext();
|
read_next(stream);
|
||||||
if (stream.name() == "link" && stream.isStartElement()) {
|
if (stream.name() == "link" && stream.isStartElement()) {
|
||||||
for (int k=0;k<stream.attributes().size();k++) {
|
for (int k=0;k<stream.attributes().size();k++) {
|
||||||
const QXmlStreamAttribute& link_attr = stream.attributes().at(k);
|
const QXmlStreamAttribute& link_attr = stream.attributes().at(k);
|
||||||
@@ -403,16 +421,19 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (cancelled) return false;
|
||||||
} else if (stream.isStartElement() && (stream.name() == "effect" || stream.name() == "opening" || stream.name() == "closing")) {
|
} else if (stream.isStartElement() && (stream.name() == "effect" || stream.name() == "opening" || stream.name() == "closing")) {
|
||||||
// "opening" and "closing" are backwards compatibility code
|
// "opening" and "closing" are backwards compatibility code
|
||||||
load_effect(stream, c);
|
load_effect(stream, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (cancelled) return false;
|
||||||
|
|
||||||
s->clips.append(c);
|
s->clips.append(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (cancelled) return false;
|
||||||
|
|
||||||
// correct links, clip IDs, transitions
|
// correct links, clip IDs, transitions
|
||||||
for (int i=0;i<s->clips.size();i++) {
|
for (int i=0;i<s->clips.size();i++) {
|
||||||
@@ -486,11 +507,12 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (cancelled) return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return !cancelled;
|
||||||
}
|
}
|
||||||
|
|
||||||
Media* LoadThread::find_loaded_folder_by_id(int id) {
|
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() {
|
void LoadThread::run() {
|
||||||
|
mutex.lock();
|
||||||
|
|
||||||
QFile file(project_url);
|
QFile file(project_url);
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
dout << "[ERROR] Could not open file";
|
dout << "[ERROR] Could not open file";
|
||||||
@@ -534,17 +558,15 @@ void LoadThread::run() {
|
|||||||
loaded_sequences.clear();
|
loaded_sequences.clear();
|
||||||
|
|
||||||
// get "element" count
|
// get "element" count
|
||||||
int element_count = 0;
|
current_element_count = 0;
|
||||||
while (!stream.atEnd()) {
|
total_element_count = 0;
|
||||||
|
while (!cancelled && !stream.atEnd()) {
|
||||||
stream.readNextStartElement();
|
stream.readNextStartElement();
|
||||||
if (stream.name() == "folder"
|
if (is_element(stream)) {
|
||||||
|| stream.name() == "footage"
|
total_element_count++;
|
||||||
|| stream.name() == "sequence"
|
|
||||||
|| stream.name() == "clip"
|
|
||||||
|| stream.name() == "effect") {
|
|
||||||
element_count++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
cont = !cancelled;
|
||||||
|
|
||||||
// find project file version
|
// find project file version
|
||||||
cont = load_worker(file, stream, LOAD_TYPE_VERSION);
|
cont = load_worker(file, stream, LOAD_TYPE_VERSION);
|
||||||
@@ -590,43 +612,105 @@ void LoadThread::run() {
|
|||||||
cont = load_worker(file, stream, MEDIA_TYPE_SEQUENCE);
|
cont = load_worker(file, stream, MEDIA_TYPE_SEQUENCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// attach nested sequence clips to their sequences
|
if (!cancelled) {
|
||||||
for (int i=0;i<loaded_clips.size();i++) {
|
if (!cont) {
|
||||||
for (int j=0;j<loaded_sequences.size();j++) {
|
if (show_err) QMessageBox::critical(mainWindow, "Project Load Error", "Error loading project: " + error_str, QMessageBox::Ok);
|
||||||
if (loaded_clips.at(i)->media == NULL && loaded_clips.at(i)->media_stream == loaded_sequences.at(j)->to_sequence()->save_id) {
|
} else if (stream.hasError()) {
|
||||||
loaded_clips.at(i)->media = loaded_sequences.at(j);
|
dout << "[ERROR] Error parsing XML." << stream.errorString();
|
||||||
loaded_clips.at(i)->refresh();
|
QMessageBox::critical(mainWindow, "XML Parsing Error", "Couldn't load '" + project_url + "'. " + stream.errorString(), QMessageBox::Ok);
|
||||||
break;
|
cont = false;
|
||||||
|
} else {
|
||||||
|
// attach nested sequence clips to their sequences
|
||||||
|
for (int i=0;i<loaded_clips.size();i++) {
|
||||||
|
for (int j=0;j<loaded_sequences.size();j++) {
|
||||||
|
if (loaded_clips.at(i)->media == 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) {
|
if (cont) {
|
||||||
mainWindow->setWindowModified(autorecovery);
|
mainWindow->setWindowModified(autorecovery);
|
||||||
|
|
||||||
|
panel_project->add_recent_project(project_url);
|
||||||
|
|
||||||
emit success(); // run in main thread
|
emit success(); // run in main thread
|
||||||
|
|
||||||
for (int i=0;i<loaded_media_items.size();i++) {
|
for (int i=0;i<loaded_media_items.size();i++) {
|
||||||
panel_project->start_preview_generator(loaded_media_items.at(i), true);
|
panel_project->start_preview_generator(loaded_media_items.at(i), true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panel_project->new_project();
|
mainWindow->new_project();
|
||||||
}
|
}
|
||||||
|
|
||||||
panel_project->add_recent_project(project_url);
|
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
|
mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadThread::cancel() {
|
||||||
|
waitCond.wakeAll();
|
||||||
|
cancelled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadThread::success_func() {
|
void LoadThread::success_func() {
|
||||||
if (open_seq != NULL) set_sequence(open_seq);
|
if (open_seq != NULL) set_sequence(open_seq);
|
||||||
update_ui(false);
|
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();
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,12 +4,15 @@
|
|||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QWaitCondition>
|
||||||
|
|
||||||
class Media;
|
class Media;
|
||||||
class Footage;
|
class Footage;
|
||||||
class Clip;
|
class Clip;
|
||||||
class Sequence;
|
class Sequence;
|
||||||
class LoadDialog;
|
class LoadDialog;
|
||||||
|
class EffectMeta;
|
||||||
|
|
||||||
class LoadThread : public QThread
|
class LoadThread : public QThread
|
||||||
{
|
{
|
||||||
@@ -17,15 +20,25 @@ class LoadThread : public QThread
|
|||||||
public:
|
public:
|
||||||
LoadThread(LoadDialog* l, bool a);
|
LoadThread(LoadDialog* l, bool a);
|
||||||
void run();
|
void run();
|
||||||
|
void cancel();
|
||||||
signals:
|
signals:
|
||||||
void success();
|
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:
|
private slots:
|
||||||
void success_func();
|
void success_func();
|
||||||
|
void create_effect_ui(QXmlStreamReader* stream, Clip* c, int type, const EffectMeta* meta, long effect_length, bool effect_enabled);
|
||||||
private:
|
private:
|
||||||
LoadDialog* ld;
|
LoadDialog* ld;
|
||||||
bool autorecovery;
|
bool autorecovery;
|
||||||
|
|
||||||
bool load_worker(QFile& f, QXmlStreamReader& stream, int type);
|
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;
|
Sequence* open_seq;
|
||||||
QVector<Media*> loaded_media_items;
|
QVector<Media*> loaded_media_items;
|
||||||
QDir proj_dir;
|
QDir proj_dir;
|
||||||
@@ -34,10 +47,20 @@ private:
|
|||||||
bool show_err;
|
bool show_err;
|
||||||
QString error_str;
|
QString error_str;
|
||||||
|
|
||||||
|
bool is_element(QXmlStreamReader& stream);
|
||||||
|
|
||||||
QVector<Media*> loaded_folders;
|
QVector<Media*> loaded_folders;
|
||||||
QVector<Clip*> loaded_clips;
|
QVector<Clip*> loaded_clips;
|
||||||
QVector<Media*> loaded_sequences;
|
QVector<Media*> loaded_sequences;
|
||||||
Media* find_loaded_folder_by_id(int id);
|
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
|
#endif // LOADTHREAD_H
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ bool PreviewGenerator::retrieve_preview(const QString& hash) {
|
|||||||
QString thumb_path = get_thumbnail_path(hash, ms);
|
QString thumb_path = get_thumbnail_path(hash, ms);
|
||||||
QFile f(thumb_path);
|
QFile f(thumb_path);
|
||||||
if (f.exists() && ms->video_preview.load(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;
|
ms->preview_done = true;
|
||||||
} else {
|
} else {
|
||||||
found = false;
|
found = false;
|
||||||
@@ -139,7 +139,7 @@ bool PreviewGenerator::retrieve_preview(const QString& hash) {
|
|||||||
QString waveform_path = get_waveform_path(hash, ms);
|
QString waveform_path = get_waveform_path(hash, ms);
|
||||||
QFile f(waveform_path);
|
QFile f(waveform_path);
|
||||||
if (f.exists()) {
|
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);
|
f.open(QFile::ReadOnly);
|
||||||
QByteArray data = f.readAll();
|
QByteArray data = f.readAll();
|
||||||
ms->audio_preview.resize(data.size());
|
ms->audio_preview.resize(data.size());
|
||||||
@@ -433,7 +433,7 @@ void PreviewGenerator::run() {
|
|||||||
// see if we already have data for this
|
// see if we already have data for this
|
||||||
QFileInfo file_info(footage->url);
|
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());
|
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();
|
QString hash = QCryptographicHash::hash(cache_file.toLatin1(), QCryptographicHash::Md5).toHex();
|
||||||
|
|
||||||
if (retrieve_preview(hash)) {
|
if (retrieve_preview(hash)) {
|
||||||
@@ -445,7 +445,7 @@ void PreviewGenerator::run() {
|
|||||||
for (int i=0;i<footage->video_tracks.size();i++) {
|
for (int i=0;i<footage->video_tracks.size();i++) {
|
||||||
FootageStream* ms = footage->video_tracks.at(i);
|
FootageStream* ms = footage->video_tracks.at(i);
|
||||||
ms->video_preview.save(get_thumbnail_path(hash, ms), "PNG");
|
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;i<footage->audio_tracks.size();i++) {
|
for (int i=0;i<footage->audio_tracks.size();i++) {
|
||||||
FootageStream* ms = footage->audio_tracks.at(i);
|
FootageStream* ms = footage->audio_tracks.at(i);
|
||||||
@@ -453,7 +453,7 @@ void PreviewGenerator::run() {
|
|||||||
f.open(QFile::WriteOnly);
|
f.open(QFile::WriteOnly);
|
||||||
f.write(ms->audio_preview.constData(), ms->audio_preview.size());
|
f.write(ms->audio_preview.constData(), ms->audio_preview.size());
|
||||||
f.close();
|
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();
|
sem.release();
|
||||||
|
|||||||
+14
-13
@@ -220,6 +220,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
connect(ui->actionCu_t, SIGNAL(triggered(bool)), this, SLOT(cut()));
|
connect(ui->actionCu_t, SIGNAL(triggered(bool)), this, SLOT(cut()));
|
||||||
connect(ui->actionCop_y, SIGNAL(triggered(bool)), this, SLOT(copy()));
|
connect(ui->actionCop_y, SIGNAL(triggered(bool)), this, SLOT(copy()));
|
||||||
connect(ui->action_Paste, SIGNAL(triggered(bool)), this, SLOT(paste()));
|
connect(ui->action_Paste, SIGNAL(triggered(bool)), this, SLOT(paste()));
|
||||||
|
connect(ui->actionProject, SIGNAL(triggered(bool)), this, SLOT(new_project()));
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow() {
|
MainWindow::~MainWindow() {
|
||||||
@@ -418,7 +419,19 @@ void MainWindow::copy() {
|
|||||||
void MainWindow::paste() {
|
void MainWindow::paste() {
|
||||||
if ((panel_timeline->focused() || panel_effect_controls->is_focused()) && sequence != NULL) {
|
if ((panel_timeline->focused() || panel_effect_controls->is_focused()) && sequence != NULL) {
|
||||||
panel_timeline->paste(false);
|
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()
|
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()
|
void MainWindow::on_actionSave_Project_As_triggered()
|
||||||
{
|
{
|
||||||
save_project_as();
|
save_project_as();
|
||||||
|
|||||||
+1
-2
@@ -28,6 +28,7 @@ public slots:
|
|||||||
void cut();
|
void cut();
|
||||||
void copy();
|
void copy();
|
||||||
void paste();
|
void paste();
|
||||||
|
void new_project();
|
||||||
void autorecover_interval();
|
void autorecover_interval();
|
||||||
void on_actionNest_triggered();
|
void on_actionNest_triggered();
|
||||||
|
|
||||||
@@ -70,8 +71,6 @@ private slots:
|
|||||||
|
|
||||||
void on_action_Open_Project_triggered();
|
void on_action_Open_Project_triggered();
|
||||||
|
|
||||||
void on_actionProject_triggered();
|
|
||||||
|
|
||||||
void on_actionSave_Project_As_triggered();
|
void on_actionSave_Project_As_triggered();
|
||||||
|
|
||||||
void on_actionDeselect_All_triggered();
|
void on_actionDeselect_All_triggered();
|
||||||
|
|||||||
+5
-10
@@ -62,11 +62,7 @@ Project::Project(QWidget *parent) :
|
|||||||
|
|
||||||
sorter = new QSortFilterProxyModel(this);
|
sorter = new QSortFilterProxyModel(this);
|
||||||
sorter->setSourceModel(&project_model);
|
sorter->setSourceModel(&project_model);
|
||||||
|
|
||||||
source_table->setModel(sorter);
|
source_table->setModel(sorter);
|
||||||
|
|
||||||
/*Media* m = new Media(project_model.get_root());
|
|
||||||
project_model.get_root()->appendChild(m);*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Project::~Project() {
|
Project::~Project() {
|
||||||
@@ -738,7 +734,6 @@ void Project::new_project() {
|
|||||||
set_sequence(NULL);
|
set_sequence(NULL);
|
||||||
panel_footage_viewer->set_media(NULL);
|
panel_footage_viewer->set_media(NULL);
|
||||||
clear();
|
clear();
|
||||||
panel_project->source_table->update();
|
|
||||||
mainWindow->setWindowModified(false);
|
mainWindow->setWindowModified(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1038,7 +1033,7 @@ void MediaThrobber::animation_update() {
|
|||||||
if (animation == THROBBER_LIMIT) {
|
if (animation == THROBBER_LIMIT) {
|
||||||
animation = 0;
|
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++;
|
animation++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1049,10 +1044,10 @@ void MediaThrobber::stop(int icon_type, bool replace) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (icon_type) {
|
switch (icon_type) {
|
||||||
case ICON_TYPE_VIDEO: item->set_icon(QIcon(":/icons/videosource.png")); break;
|
case ICON_TYPE_VIDEO: project_model.set_icon(item, QIcon(":/icons/videosource.png")); break;
|
||||||
case ICON_TYPE_AUDIO: item->set_icon(QIcon(":/icons/audiosource.png")); break;
|
case ICON_TYPE_AUDIO: project_model.set_icon(item, QIcon(":/icons/audiosource.png")); break;
|
||||||
case ICON_TYPE_IMAGE: item->set_icon(QIcon(":/icons/imagesource.png")); break;
|
case ICON_TYPE_IMAGE: project_model.set_icon(item, QIcon(":/icons/imagesource.png")); break;
|
||||||
case ICON_TYPE_ERROR: item->set_icon(QIcon(":/icons/error.png")); break;
|
case ICON_TYPE_ERROR: project_model.set_icon(item, QIcon(":/icons/error.png")); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// refresh all clips
|
// refresh all clips
|
||||||
|
|||||||
+14
-6
@@ -868,13 +868,21 @@ void Effect::gizmo_move(EffectGizmo* gizmo, int x_movement, int y_movement, doub
|
|||||||
if (gizmos.at(i) == gizmo) {
|
if (gizmos.at(i) == gizmo) {
|
||||||
ComboAction* ca = NULL;
|
ComboAction* ca = NULL;
|
||||||
if (done) ca = new ComboAction();
|
if (done) ca = new ComboAction();
|
||||||
if (gizmo->x_field != NULL) {
|
if (gizmo->x_field1 != NULL) {
|
||||||
gizmo->x_field->set_double_value(gizmo->x_field->get_double_value(timecode) + x_movement*gizmo->x_field_multi);
|
gizmo->x_field1->set_double_value(gizmo->x_field1->get_double_value(timecode) + x_movement*gizmo->x_field_multi1);
|
||||||
gizmo->x_field->make_key_from_change(ca);
|
gizmo->x_field1->make_key_from_change(ca);
|
||||||
}
|
}
|
||||||
if (gizmo->y_field != NULL) {
|
if (gizmo->y_field1 != NULL) {
|
||||||
gizmo->y_field->set_double_value(gizmo->y_field->get_double_value(timecode) + y_movement*gizmo->y_field_multi);
|
gizmo->y_field1->set_double_value(gizmo->y_field1->get_double_value(timecode) + y_movement*gizmo->y_field_multi1);
|
||||||
gizmo->y_field->make_key_from_change(ca);
|
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);
|
if (done) undo_stack.push(ca);
|
||||||
break;
|
break;
|
||||||
|
|||||||
+12
-6
@@ -4,10 +4,14 @@
|
|||||||
#include "effectfield.h"
|
#include "effectfield.h"
|
||||||
|
|
||||||
EffectGizmo::EffectGizmo(int type) :
|
EffectGizmo::EffectGizmo(int type) :
|
||||||
x_field(NULL),
|
x_field1(NULL),
|
||||||
x_field_multi(1.0),
|
x_field_multi1(1.0),
|
||||||
y_field(NULL),
|
y_field1(NULL),
|
||||||
y_field_multi(1.0),
|
y_field_multi1(1.0),
|
||||||
|
x_field2(NULL),
|
||||||
|
x_field_multi2(1.0),
|
||||||
|
y_field2(NULL),
|
||||||
|
y_field_multi2(1.0),
|
||||||
type(type),
|
type(type),
|
||||||
cursor(-1)
|
cursor(-1)
|
||||||
{
|
{
|
||||||
@@ -19,8 +23,10 @@ EffectGizmo::EffectGizmo(int type) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EffectGizmo::set_previous_value() {
|
void EffectGizmo::set_previous_value() {
|
||||||
if (x_field != NULL) static_cast<LabelSlider*>(x_field->ui_element)->set_previous_value();
|
if (x_field1 != NULL) static_cast<LabelSlider*>(x_field1->ui_element)->set_previous_value();
|
||||||
if (y_field != NULL) static_cast<LabelSlider*>(y_field->ui_element)->set_previous_value();
|
if (y_field1 != NULL) static_cast<LabelSlider*>(y_field1->ui_element)->set_previous_value();
|
||||||
|
if (x_field2 != NULL) static_cast<LabelSlider*>(x_field2->ui_element)->set_previous_value();
|
||||||
|
if (y_field2 != NULL) static_cast<LabelSlider*>(y_field2->ui_element)->set_previous_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
int EffectGizmo::get_point_count() {
|
int EffectGizmo::get_point_count() {
|
||||||
|
|||||||
@@ -24,10 +24,14 @@ public:
|
|||||||
QVector<QPoint> world_pos;
|
QVector<QPoint> world_pos;
|
||||||
QVector<QPoint> screen_pos;
|
QVector<QPoint> screen_pos;
|
||||||
|
|
||||||
EffectField* x_field;
|
EffectField* x_field1;
|
||||||
double x_field_multi;
|
double x_field_multi1;
|
||||||
EffectField* y_field;
|
EffectField* y_field1;
|
||||||
double y_field_multi;
|
double y_field_multi1;
|
||||||
|
EffectField* x_field2;
|
||||||
|
double x_field_multi2;
|
||||||
|
EffectField* y_field2;
|
||||||
|
double y_field_multi2;
|
||||||
|
|
||||||
void set_previous_value();
|
void set_previous_value();
|
||||||
|
|
||||||
|
|||||||
@@ -19,15 +19,13 @@ void ProjectModel::destroy_root() {
|
|||||||
if (panel_footage_viewer != NULL) panel_footage_viewer->viewer_widget->delete_function();
|
if (panel_footage_viewer != NULL) panel_footage_viewer->viewer_widget->delete_function();
|
||||||
|
|
||||||
if (root_item != NULL) {
|
if (root_item != NULL) {
|
||||||
beginRemoveRows(QModelIndex(), 0, root_item->childCount());
|
|
||||||
delete root_item;
|
delete root_item;
|
||||||
endRemoveRows();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProjectModel::clear() {
|
void ProjectModel::clear() {
|
||||||
destroy_root();
|
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
|
destroy_root();
|
||||||
root_item = new Media(0);
|
root_item = new Media(0);
|
||||||
root_item->root = true;
|
root_item->root = true;
|
||||||
endResetModel();
|
endResetModel();
|
||||||
@@ -132,6 +130,13 @@ Media *ProjectModel::getItem(const QModelIndex &index) const {
|
|||||||
return root_item;
|
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) {
|
void ProjectModel::appendChild(Media *parent, Media *child) {
|
||||||
if (parent == NULL) parent = root_item;
|
if (parent == NULL) parent = root_item;
|
||||||
beginInsertRows(parent == root_item ? QModelIndex() : createIndex(parent->row(), 0, parent), parent->childCount(), parent->childCount());
|
beginInsertRows(parent == root_item ? QModelIndex() : createIndex(parent->row(), 0, parent), parent->childCount(), parent->childCount());
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ public:
|
|||||||
void removeChild(Media *parent, Media* m);
|
void removeChild(Media *parent, Media* m);
|
||||||
Media *child(int i, Media* parent = NULL);
|
Media *child(int i, Media* parent = NULL);
|
||||||
int childCount(Media* parent = NULL);
|
int childCount(Media* parent = NULL);
|
||||||
|
void set_icon(Media* m, const QIcon &ico);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Media* root_item;
|
Media* root_item;
|
||||||
|
|||||||
Reference in New Issue
Block a user