massive rewrite of project data system
This commit is contained in:
+48
-57
@@ -2,13 +2,14 @@
|
||||
|
||||
#include "project/effect.h"
|
||||
#include "project/transition.h"
|
||||
#include "io/media.h"
|
||||
#include "project/footage.h"
|
||||
#include "io/config.h"
|
||||
#include "playback/playback.h"
|
||||
#include "playback/cacher.h"
|
||||
#include "panels/project.h"
|
||||
#include "project/sequence.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "project/media.h"
|
||||
#include "undo.h"
|
||||
|
||||
extern "C" {
|
||||
@@ -35,7 +36,6 @@ Clip::Clip(Sequence* s) :
|
||||
use_existing_frame(false),
|
||||
filter_graph(NULL),
|
||||
fbo(NULL),
|
||||
texture(NULL),
|
||||
opts(NULL)
|
||||
{
|
||||
pkt = av_packet_alloc();
|
||||
@@ -55,7 +55,6 @@ Clip* Clip::copy(Sequence* s) {
|
||||
copy->color_g = color_g;
|
||||
copy->color_b = color_b;
|
||||
copy->media = media;
|
||||
copy->media_type = media_type;
|
||||
copy->media_stream = media_stream;
|
||||
copy->autoscale = autoscale;
|
||||
copy->speed = speed;
|
||||
@@ -93,29 +92,23 @@ void Clip::reset() {
|
||||
}
|
||||
|
||||
void Clip::reset_audio() {
|
||||
switch (media_type) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
case MEDIA_TYPE_TONE:
|
||||
if (media == NULL || media->get_type() == MEDIA_TYPE_FOOTAGE) {
|
||||
audio_reset = true;
|
||||
frame_sample_index = -1;
|
||||
audio_buffer_write = 0;
|
||||
break;
|
||||
case MEDIA_TYPE_SEQUENCE:
|
||||
{
|
||||
Sequence* nested_sequence = static_cast<Sequence*>(media);
|
||||
frame_sample_index = -1;
|
||||
audio_buffer_write = 0;
|
||||
} else if (media->get_type() == MEDIA_TYPE_SEQUENCE) {
|
||||
Sequence* nested_sequence = media->to_sequence();
|
||||
for (int i=0;i<nested_sequence->clips.size();i++) {
|
||||
Clip* c = nested_sequence->clips.at(i);
|
||||
if (c != NULL) c->reset_audio();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Clip::refresh() {
|
||||
// validates media if it was replaced
|
||||
if (replaced && media_type == MEDIA_TYPE_FOOTAGE) {
|
||||
Media* m = static_cast<Media*>(media);
|
||||
if (replaced && media != NULL && media->get_type() == MEDIA_TYPE_FOOTAGE) {
|
||||
Footage* m = media->to_footage();
|
||||
media_stream = (track < 0) ? m->video_tracks.at(0)->file_index : m->audio_tracks.at(0)->file_index;
|
||||
}
|
||||
replaced = false;
|
||||
@@ -166,7 +159,7 @@ Clip::~Clip() {
|
||||
close_clip(this);
|
||||
|
||||
// make sure clip has closed before clip is destroyed
|
||||
if (multithreaded && media_type == MEDIA_TYPE_FOOTAGE) {
|
||||
if (multithreaded && media != NULL && media->get_type() == MEDIA_TYPE_FOOTAGE) {
|
||||
cacher->wait();
|
||||
}
|
||||
}
|
||||
@@ -210,36 +203,44 @@ long Clip::getLength() {
|
||||
return timeline_out - timeline_in;
|
||||
}
|
||||
|
||||
double Clip::getMediaFrameRate() {
|
||||
Q_ASSERT(track < 0);
|
||||
if (media != NULL) {
|
||||
double rate = media->get_frame_rate(media_stream);
|
||||
if (!qIsNaN(rate)) return rate;
|
||||
}
|
||||
if (sequence != NULL) return sequence->frame_rate;
|
||||
}
|
||||
|
||||
void Clip::recalculateMaxLength() {
|
||||
if (sequence != NULL) {
|
||||
double fr = this->sequence->frame_rate;
|
||||
|
||||
fr /= speed;
|
||||
|
||||
switch (media_type) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
{
|
||||
Media* m = static_cast<Media*>(media);
|
||||
MediaStream* ms = m->get_stream_from_file_index(track < 0, media_stream);
|
||||
if (ms != NULL && ms->infinite_length) {
|
||||
calculated_length = LONG_MAX;
|
||||
} else {
|
||||
calculated_length = m->get_length_in_frames(fr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MEDIA_TYPE_SEQUENCE:
|
||||
{
|
||||
Sequence* s = static_cast<Sequence*>(media);
|
||||
calculated_length = refactor_frame_number(s->getEndFrame(), s->frame_rate, fr);
|
||||
}
|
||||
break;
|
||||
/*case MEDIA_TYPE_SOLID:
|
||||
case MEDIA_TYPE_TONE:*/
|
||||
default:
|
||||
calculated_length = LONG_MAX;
|
||||
break;
|
||||
}
|
||||
calculated_length = LONG_MAX;
|
||||
|
||||
if (media != NULL) {
|
||||
switch (media->get_type()) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
{
|
||||
Footage* m = media->to_footage();
|
||||
FootageStream* ms = m->get_stream_from_file_index(track < 0, media_stream);
|
||||
if (ms != NULL && ms->infinite_length) {
|
||||
calculated_length = LONG_MAX;
|
||||
} else {
|
||||
calculated_length = m->get_length_in_frames(fr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MEDIA_TYPE_SEQUENCE:
|
||||
{
|
||||
Sequence* s = media->to_sequence();
|
||||
calculated_length = refactor_frame_number(s->getEndFrame(), s->frame_rate, fr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,28 +248,18 @@ long Clip::getMaximumLength() {
|
||||
return calculated_length;
|
||||
}
|
||||
|
||||
double Clip::getMediaFrameRate() {
|
||||
Q_ASSERT(track < 0);
|
||||
switch (media_type) {
|
||||
case MEDIA_TYPE_FOOTAGE: return static_cast<Media*>(media)->get_stream_from_file_index(track < 0, media_stream)->video_frame_rate;
|
||||
case MEDIA_TYPE_SEQUENCE: return static_cast<Sequence*>(media)->frame_rate;
|
||||
}
|
||||
if (sequence != NULL) return sequence->frame_rate;
|
||||
return qSNaN();
|
||||
}
|
||||
|
||||
int Clip::getWidth() {
|
||||
if (media == NULL && sequence != NULL) return sequence->width;
|
||||
switch (media_type) {
|
||||
switch (media->get_type()) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
{
|
||||
MediaStream* ms = static_cast<Media*>(media)->get_stream_from_file_index(track < 0, media_stream);
|
||||
FootageStream* ms = media->to_footage()->get_stream_from_file_index(track < 0, media_stream);
|
||||
if (ms != NULL) return ms->video_width;
|
||||
if (sequence != NULL) return sequence->width;
|
||||
}
|
||||
case MEDIA_TYPE_SEQUENCE:
|
||||
{
|
||||
Sequence* s = static_cast<Sequence*>(media);
|
||||
Sequence* s = media->to_sequence();
|
||||
return s->width;
|
||||
}
|
||||
}
|
||||
@@ -277,16 +268,16 @@ int Clip::getWidth() {
|
||||
|
||||
int Clip::getHeight() {
|
||||
if (media == NULL && sequence != NULL) return sequence->height;
|
||||
switch (media_type) {
|
||||
switch (media->get_type()) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
{
|
||||
MediaStream* ms = static_cast<Media*>(media)->get_stream_from_file_index(track < 0, media_stream);
|
||||
FootageStream* ms = media->to_footage()->get_stream_from_file_index(track < 0, media_stream);
|
||||
if (ms != NULL) return ms->video_height;
|
||||
if (sequence != NULL) return sequence->height;
|
||||
}
|
||||
case MEDIA_TYPE_SEQUENCE:
|
||||
{
|
||||
Sequence* s = static_cast<Sequence*>(media);
|
||||
Sequence* s = media->to_sequence();
|
||||
return s->height;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -13,9 +13,10 @@ class Effect;
|
||||
class Transition;
|
||||
class QOpenGLFramebufferObject;
|
||||
class ComboAction;
|
||||
class Media;
|
||||
struct Sequence;
|
||||
struct Media;
|
||||
struct MediaStream;
|
||||
struct Footage;
|
||||
struct FootageStream;
|
||||
|
||||
struct AVFormatContext;
|
||||
struct AVStream;
|
||||
@@ -42,9 +43,9 @@ struct Clip
|
||||
long get_timeline_in_with_transition();
|
||||
long get_timeline_out_with_transition();
|
||||
long getLength();
|
||||
double getMediaFrameRate();
|
||||
long getMaximumLength();
|
||||
void recalculateMaxLength();
|
||||
double getMediaFrameRate();
|
||||
int getWidth();
|
||||
int getHeight();
|
||||
void refactor_frame_rate(ComboAction* ca, double multiplier, bool change_timeline_points);
|
||||
@@ -64,8 +65,7 @@ struct Clip
|
||||
quint8 color_r;
|
||||
quint8 color_g;
|
||||
quint8 color_b;
|
||||
void* media; // attached media
|
||||
int media_type;
|
||||
Media* media;
|
||||
int media_stream;
|
||||
double speed;
|
||||
double cached_fr;
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#include "footage.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QtMath>
|
||||
#include "io/previewgenerator.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
}
|
||||
|
||||
#include "project/clip.h"
|
||||
|
||||
Footage::Footage() : ready(false), preview_gen(NULL), invalid(false), in(0), out(0) {
|
||||
ready_lock.lock();
|
||||
}
|
||||
|
||||
Footage::~Footage() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void Footage::reset() {
|
||||
if (preview_gen != NULL) {
|
||||
preview_gen->cancel();
|
||||
preview_gen->wait();
|
||||
}
|
||||
for (int i=0;i<video_tracks.size();i++) {
|
||||
delete video_tracks.at(i);
|
||||
}
|
||||
for (int i=0;i<audio_tracks.size();i++) {
|
||||
delete audio_tracks.at(i);
|
||||
}
|
||||
video_tracks.clear();
|
||||
audio_tracks.clear();
|
||||
ready = false;
|
||||
}
|
||||
|
||||
long Footage::get_length_in_frames(double frame_rate) {
|
||||
if (length >= 0) return qFloor(((double) length / (double) AV_TIME_BASE) * frame_rate);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FootageStream* Footage::get_stream_from_file_index(bool video, int index) {
|
||||
if (video) {
|
||||
for (int i=0;i<video_tracks.size();i++) {
|
||||
if (video_tracks.at(i)->file_index == index) {
|
||||
return video_tracks.at(i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i=0;i<audio_tracks.size();i++) {
|
||||
if (audio_tracks.at(i)->file_index == index) {
|
||||
return audio_tracks.at(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#ifndef FOOTAGE_H
|
||||
#define FOOTAGE_H
|
||||
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QMetaType>
|
||||
#include <QVariant>
|
||||
#include <QMutex>
|
||||
#include <QPixmap>
|
||||
|
||||
#define VIDEO_PROGRESSIVE 0
|
||||
#define VIDEO_TOP_FIELD_FIRST 1
|
||||
#define VIDEO_BOTTOM_FIELD_FIRST 2
|
||||
|
||||
struct Sequence;
|
||||
struct Clip;
|
||||
class PreviewGenerator;
|
||||
class MediaThrobber;
|
||||
|
||||
struct FootageStream {
|
||||
int file_index;
|
||||
int video_width;
|
||||
int video_height;
|
||||
bool infinite_length;
|
||||
double video_frame_rate;
|
||||
int video_interlacing;
|
||||
int video_auto_interlacing;
|
||||
int audio_channels;
|
||||
int audio_layout;
|
||||
int audio_frequency;
|
||||
|
||||
// preview thumbnail/waveform
|
||||
bool preview_done;
|
||||
QImage video_preview;
|
||||
QVector<char> audio_preview;
|
||||
};
|
||||
|
||||
struct Footage {
|
||||
Footage();
|
||||
~Footage();
|
||||
|
||||
QString url;
|
||||
QString name;
|
||||
int64_t length;
|
||||
QVector<FootageStream*> video_tracks;
|
||||
QVector<FootageStream*> audio_tracks;
|
||||
int save_id;
|
||||
bool ready;
|
||||
bool invalid;
|
||||
|
||||
PreviewGenerator* preview_gen;
|
||||
QMutex ready_lock;
|
||||
|
||||
bool using_inout;
|
||||
long in;
|
||||
long out;
|
||||
|
||||
long get_length_in_frames(double frame_rate);
|
||||
FootageStream* get_stream_from_file_index(bool video, int index);
|
||||
void reset();
|
||||
};
|
||||
|
||||
#endif // FOOTAGE_H
|
||||
@@ -0,0 +1,312 @@
|
||||
#include "media.h"
|
||||
|
||||
#include "footage.h"
|
||||
#include "sequence.h"
|
||||
#include "undo.h"
|
||||
#include "io/config.h"
|
||||
#include "panels/viewer.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
}
|
||||
|
||||
QString get_interlacing_name(int interlacing) {
|
||||
switch (interlacing) {
|
||||
case VIDEO_PROGRESSIVE: return "None (Progressive)";
|
||||
case VIDEO_TOP_FIELD_FIRST: return "Top Field First";
|
||||
case VIDEO_BOTTOM_FIELD_FIRST: return "Bottom Field First";
|
||||
default: return "Invalid";
|
||||
}
|
||||
}
|
||||
|
||||
QString get_channel_layout_name(int channels, uint64_t layout) {
|
||||
switch (channels) {
|
||||
case 0: return "Invalid"; break;
|
||||
case 1: return "Mono"; break;
|
||||
case 2: return "Stereo"; break;
|
||||
default: {
|
||||
char buf[50];
|
||||
av_get_channel_layout_string(buf, sizeof(buf), channels, layout);
|
||||
return QString(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Media::Media(Media* iparent) :
|
||||
parent(iparent),
|
||||
throbber(NULL),
|
||||
root(false),
|
||||
type(-1)
|
||||
{}
|
||||
|
||||
Media::~Media() {
|
||||
switch (get_type()) {
|
||||
case MEDIA_TYPE_FOOTAGE: delete to_footage(); break;
|
||||
case MEDIA_TYPE_SEQUENCE: if (object != NULL) delete to_sequence(); break;
|
||||
}
|
||||
if (throbber != NULL) delete throbber;
|
||||
qDeleteAll(children);
|
||||
}
|
||||
|
||||
Footage *Media::to_footage() {
|
||||
return static_cast<Footage*>(object);
|
||||
}
|
||||
|
||||
Sequence *Media::to_sequence() {
|
||||
return static_cast<Sequence*>(object);
|
||||
}
|
||||
|
||||
void Media::set_footage(Footage *f) {
|
||||
type = MEDIA_TYPE_FOOTAGE;
|
||||
object = f;
|
||||
}
|
||||
|
||||
void Media::set_sequence(Sequence *s) {
|
||||
set_icon(QIcon(":/icons/sequence.png"));
|
||||
type = MEDIA_TYPE_SEQUENCE;
|
||||
object = s;
|
||||
if (s != NULL) update_tooltip();
|
||||
}
|
||||
|
||||
void Media::set_folder() {
|
||||
if (folder_name.isEmpty()) folder_name = "New Folder";
|
||||
set_icon(QIcon(":/icons/folder.png"));
|
||||
type = MEDIA_TYPE_FOLDER;
|
||||
object = NULL;
|
||||
}
|
||||
|
||||
void Media::set_icon(const QIcon &ico) {
|
||||
icon = ico;
|
||||
}
|
||||
|
||||
void Media::set_parent(Media *p) {
|
||||
parent = p;
|
||||
}
|
||||
|
||||
void Media::update_tooltip(const QString& error) {
|
||||
switch (type) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
{
|
||||
Footage* f = to_footage();
|
||||
tooltip = "Name: " + f->name + "\nFilename: " + f->url + "\n";
|
||||
|
||||
if (error.isEmpty()) {
|
||||
if (f->video_tracks.size() > 0) {
|
||||
tooltip += "Video Dimensions: ";
|
||||
for (int i=0;i<f->video_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
tooltip += QString::number(f->video_tracks.at(i)->video_width) + "x" + QString::number(f->video_tracks.at(i)->video_height);
|
||||
}
|
||||
tooltip += "\n";
|
||||
|
||||
if (!f->video_tracks.at(0)->infinite_length) {
|
||||
tooltip += "Frame Rate: ";
|
||||
for (int i=0;i<f->video_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
if (f->video_tracks.at(i)->video_interlacing == VIDEO_PROGRESSIVE) {
|
||||
tooltip += QString::number(f->video_tracks.at(i)->video_frame_rate);
|
||||
} else {
|
||||
tooltip += QString::number(f->video_tracks.at(i)->video_frame_rate * 2);
|
||||
tooltip += " fields (" + QString::number(f->video_tracks.at(i)->video_frame_rate) + " frames)";
|
||||
}
|
||||
}
|
||||
tooltip += "\n";
|
||||
}
|
||||
|
||||
tooltip += "Interlacing: ";
|
||||
for (int i=0;i<f->video_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
tooltip += get_interlacing_name(f->video_tracks.at(i)->video_interlacing);
|
||||
}
|
||||
}
|
||||
|
||||
if (f->audio_tracks.size() > 0) {
|
||||
tooltip += "\n";
|
||||
|
||||
tooltip += "Audio Frequency: ";
|
||||
for (int i=0;i<f->audio_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
tooltip += QString::number(f->audio_tracks.at(i)->audio_frequency);
|
||||
}
|
||||
tooltip += "\n";
|
||||
|
||||
tooltip += "Audio Channels: ";
|
||||
for (int i=0;i<f->audio_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
tooltip += get_channel_layout_name(f->audio_tracks.at(i)->audio_channels, f->audio_tracks.at(i)->audio_layout);
|
||||
}
|
||||
// tooltip += "\n";
|
||||
}
|
||||
} else {
|
||||
tooltip += error;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MEDIA_TYPE_SEQUENCE:
|
||||
{
|
||||
Sequence* s = to_sequence();
|
||||
tooltip = "Name: " + s->name
|
||||
+ "\nVideo Dimensions: " + QString::number(s->width) + "x" + QString::number(s->height)
|
||||
+ "\nFrame Rate: " + QString::number(s->frame_rate)
|
||||
+ "\nAudio Frequency: " + QString::number(s->audio_frequency)
|
||||
+ "\nAudio Layout: " + get_channel_layout_name(av_get_channel_layout_nb_channels(s->audio_layout), s->audio_layout);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void *Media::to_object() {
|
||||
return object;
|
||||
}
|
||||
|
||||
int Media::get_type() {
|
||||
return type;
|
||||
}
|
||||
|
||||
const QString &Media::get_name() {
|
||||
switch (type) {
|
||||
case MEDIA_TYPE_FOOTAGE: return to_footage()->name;
|
||||
case MEDIA_TYPE_SEQUENCE: return to_sequence()->name;
|
||||
case MEDIA_TYPE_FOLDER: return folder_name;
|
||||
}
|
||||
}
|
||||
|
||||
void Media::set_name(const QString &n) {
|
||||
switch (type) {
|
||||
case MEDIA_TYPE_FOOTAGE: to_footage()->name = n; break;
|
||||
case MEDIA_TYPE_SEQUENCE: to_sequence()->name = n; break;
|
||||
case MEDIA_TYPE_FOLDER: folder_name = n; break;
|
||||
}
|
||||
}
|
||||
|
||||
double Media::get_frame_rate(int stream) {
|
||||
switch (get_type()) {
|
||||
case MEDIA_TYPE_FOOTAGE: return to_footage()->get_stream_from_file_index(true, stream)->video_frame_rate;
|
||||
case MEDIA_TYPE_SEQUENCE: return to_sequence()->frame_rate;
|
||||
}
|
||||
return qSNaN();
|
||||
}
|
||||
|
||||
int Media::get_sampling_rate(int stream) {
|
||||
switch (get_type()) {
|
||||
case MEDIA_TYPE_FOOTAGE: return to_footage()->get_stream_from_file_index(false, stream)->audio_frequency;
|
||||
case MEDIA_TYPE_SEQUENCE: return to_sequence()->audio_frequency;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Media::appendChild(Media *child) {
|
||||
child->set_parent(this);
|
||||
children.append(child);
|
||||
}
|
||||
|
||||
bool Media::setData(int col, const QVariant &value) {
|
||||
if (col == 0) {
|
||||
QString n = value.toString();
|
||||
if (!n.isEmpty() && get_name() != n) {
|
||||
undo_stack.push(new MediaRename(this, value.toString()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Media *Media::child(int row) {
|
||||
return children.value(row);
|
||||
}
|
||||
|
||||
int Media::childCount() const {
|
||||
return children.count();
|
||||
}
|
||||
|
||||
int Media::columnCount() const {
|
||||
return 3;
|
||||
}
|
||||
|
||||
QVariant Media::data(int column, int role) {
|
||||
switch (role) {
|
||||
case Qt::DecorationRole:
|
||||
if (column == 0) {
|
||||
return icon;
|
||||
}
|
||||
break;
|
||||
case Qt::DisplayRole:
|
||||
switch (column) {
|
||||
case 0: return (root) ? "Name" : get_name();
|
||||
case 1:
|
||||
if (root) return "Duration";
|
||||
if (get_type() == MEDIA_TYPE_SEQUENCE) {
|
||||
Sequence* s = to_sequence();
|
||||
return frame_to_timecode(s->getEndFrame(), config.timecode_view, s->frame_rate);
|
||||
}
|
||||
if (get_type() == MEDIA_TYPE_FOOTAGE) {
|
||||
Footage* f = to_footage();
|
||||
double r = 30;
|
||||
|
||||
if (f->video_tracks.size() > 0) r = f->video_tracks.at(0)->video_frame_rate;
|
||||
if (!qIsNull(r)) {
|
||||
long len = f->get_length_in_frames(r);
|
||||
if (len > 0) return frame_to_timecode(len, config.timecode_view, r);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (root) return "Rate";
|
||||
if (get_type() == MEDIA_TYPE_SEQUENCE) return QString::number(get_frame_rate()) + " FPS";
|
||||
if (get_type() == MEDIA_TYPE_FOOTAGE) {
|
||||
Footage* f = to_footage();
|
||||
if (f->video_tracks.size() > 0) {
|
||||
double r = get_frame_rate();
|
||||
if (!qIsNull(r)) return QString::number(get_frame_rate()) + " FPS";
|
||||
} else if (f->audio_tracks.size() > 0) {
|
||||
return QString::number(get_sampling_rate()) + " Hz";
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Qt::ToolTipRole:
|
||||
return tooltip;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int Media::row() const {
|
||||
if (parent) {
|
||||
return parent->children.indexOf(const_cast<Media*>(this));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Media *Media::parentItem() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
Media *Media::takeChild(int i) {
|
||||
Media* ref = children.at(i);
|
||||
children.removeAt(i);
|
||||
return ref;
|
||||
}
|
||||
|
||||
void Media::removeChild(Media* m) {
|
||||
for (int i=0;i<children.size();i++) {
|
||||
if (children.at(i) == m) {
|
||||
children.removeAt(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
#ifndef MEDIA_H
|
||||
#define MEDIA_H
|
||||
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
|
||||
#define MEDIA_TYPE_FOOTAGE 0
|
||||
#define MEDIA_TYPE_SEQUENCE 1
|
||||
#define MEDIA_TYPE_FOLDER 2
|
||||
#define MEDIA_TYPE_SOLID 3
|
||||
#define MEDIA_TYPE_TONE 4
|
||||
|
||||
class Footage;
|
||||
class MediaThrobber;
|
||||
struct Sequence;
|
||||
#include <QIcon>
|
||||
|
||||
class Media
|
||||
{
|
||||
public:
|
||||
Media(Media* iparent);
|
||||
~Media();
|
||||
Footage *to_footage();
|
||||
Sequence* to_sequence();
|
||||
void set_footage(Footage* f);
|
||||
void set_sequence(Sequence* s);
|
||||
void set_folder();
|
||||
void set_icon(const QIcon &ico);
|
||||
void set_parent(Media* p);
|
||||
void update_tooltip(const QString& error = 0);
|
||||
void *to_object();
|
||||
int get_type();
|
||||
const QString& get_name();
|
||||
void set_name(const QString& n);
|
||||
MediaThrobber* throbber;
|
||||
|
||||
double get_frame_rate(int stream = 0);
|
||||
int get_sampling_rate(int stream = 0);
|
||||
|
||||
// item functions
|
||||
void appendChild(Media *child);
|
||||
bool setData(int col, const QVariant &value);
|
||||
Media *child(int row);
|
||||
int childCount() const;
|
||||
int columnCount() const;
|
||||
QVariant data(int column, int role);
|
||||
int row() const;
|
||||
Media *parentItem();
|
||||
Media* takeChild(int i);
|
||||
void removeChild(Media* m);
|
||||
|
||||
bool root;
|
||||
int temp_id;
|
||||
int temp_id2;
|
||||
private:
|
||||
int type;
|
||||
void* object;
|
||||
|
||||
// item functions
|
||||
QList<Media*> children;
|
||||
Media* parent;
|
||||
QString folder_name;
|
||||
QString tooltip;
|
||||
QIcon icon;
|
||||
};
|
||||
|
||||
#endif // MEDIA_H
|
||||
@@ -0,0 +1,146 @@
|
||||
#include "projectmodel.h"
|
||||
|
||||
#include "panels/panels.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "ui/viewerwidget.h"
|
||||
#include "project/media.h"
|
||||
#include "debug.h"
|
||||
|
||||
ProjectModel::ProjectModel(QObject *parent) : QAbstractItemModel(parent), root_item(NULL) {
|
||||
clear();
|
||||
}
|
||||
|
||||
ProjectModel::~ProjectModel() {
|
||||
destroy_root();
|
||||
}
|
||||
|
||||
void ProjectModel::destroy_root() {
|
||||
if (panel_sequence_viewer != NULL) panel_sequence_viewer->viewer_widget->delete_function();
|
||||
if (panel_footage_viewer != NULL) panel_footage_viewer->viewer_widget->delete_function();
|
||||
|
||||
if (root_item != NULL) delete root_item;
|
||||
}
|
||||
|
||||
void ProjectModel::clear() {
|
||||
destroy_root();
|
||||
root_item = new Media(0);
|
||||
root_item->root = true;
|
||||
update_data();
|
||||
}
|
||||
|
||||
Media *ProjectModel::get_root() {
|
||||
return root_item;
|
||||
}
|
||||
|
||||
QVariant ProjectModel::data(const QModelIndex &index, int role) const {
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
return static_cast<Media*>(index.internalPointer())->data(index.column(), role);
|
||||
}
|
||||
|
||||
Qt::ItemFlags ProjectModel::flags(const QModelIndex &index) const {
|
||||
if (!index.isValid())
|
||||
return Qt::ItemIsDropEnabled;
|
||||
|
||||
return QAbstractItemModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable;
|
||||
}
|
||||
|
||||
QVariant ProjectModel::headerData(int section, Qt::Orientation orientation, int role) const {
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||
return root_item->data(section, role);
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QModelIndex ProjectModel::index(int row, int column, const QModelIndex &parent) const {
|
||||
if (!hasIndex(row, column, parent))
|
||||
return QModelIndex();
|
||||
|
||||
Media *parentItem;
|
||||
|
||||
if (!parent.isValid())
|
||||
parentItem = root_item;
|
||||
else
|
||||
parentItem = static_cast<Media*>(parent.internalPointer());
|
||||
|
||||
Media *childItem = parentItem->child(row);
|
||||
if (childItem)
|
||||
return createIndex(row, column, childItem);
|
||||
else
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex ProjectModel::parent(const QModelIndex &index) const {
|
||||
if (!index.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
Media *childItem = static_cast<Media*>(index.internalPointer());
|
||||
Media *parentItem = childItem->parentItem();
|
||||
|
||||
if (parentItem == root_item)
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex(parentItem->row(), 0, parentItem);
|
||||
}
|
||||
|
||||
bool ProjectModel::setData(const QModelIndex &index, const QVariant &value, int role) {
|
||||
if (role != Qt::EditRole)
|
||||
return false;
|
||||
|
||||
Media *item = static_cast<Media*>(index.internalPointer());
|
||||
bool result = item->setData(index.column(), value);
|
||||
|
||||
if (result)
|
||||
emit dataChanged(index, index);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int ProjectModel::rowCount(const QModelIndex &parent) const {
|
||||
Media *parentItem;
|
||||
if (parent.column() > 0)
|
||||
return 0;
|
||||
|
||||
if (!parent.isValid()) {
|
||||
parentItem = root_item;
|
||||
} else {
|
||||
parentItem = static_cast<Media*>(parent.internalPointer());
|
||||
}
|
||||
|
||||
return parentItem->childCount();
|
||||
}
|
||||
|
||||
int ProjectModel::columnCount(const QModelIndex &parent) const {
|
||||
if (parent.isValid())
|
||||
return static_cast<Media*>(parent.internalPointer())->columnCount();
|
||||
else
|
||||
return root_item->columnCount();
|
||||
}
|
||||
|
||||
int ProjectModel::topLevelItemCount() {
|
||||
return root_item->childCount();
|
||||
}
|
||||
|
||||
Media *ProjectModel::topLevelItem(int i) {
|
||||
return root_item->child(i);
|
||||
}
|
||||
|
||||
void ProjectModel::addTopLevelItem(Media *m) {
|
||||
root_item->appendChild(m);
|
||||
}
|
||||
|
||||
Media *ProjectModel::takeTopLevelItem(int i) {
|
||||
Media* ref = root_item->child(i);
|
||||
root_item->takeChild(i);
|
||||
return ref;
|
||||
}
|
||||
|
||||
void ProjectModel::removeTopLevelItem(Media *m) {
|
||||
root_item->removeChild(m);
|
||||
}
|
||||
|
||||
void ProjectModel::update_data() {
|
||||
// emit dataChanged();
|
||||
emit layoutChanged();
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef PROJECTMODEL_H
|
||||
#define PROJECTMODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
class Media;
|
||||
|
||||
class ProjectModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ProjectModel(QObject* parent = 0);
|
||||
~ProjectModel() override;
|
||||
|
||||
void destroy_root();
|
||||
void clear();
|
||||
Media* get_root();
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const override;
|
||||
QModelIndex index(int row, int column,
|
||||
const QModelIndex &parent = QModelIndex()) const override;
|
||||
QModelIndex parent(const QModelIndex &index) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int topLevelItemCount();
|
||||
Media* topLevelItem(int i);
|
||||
void addTopLevelItem(Media*);
|
||||
Media* takeTopLevelItem(int i);
|
||||
void removeTopLevelItem(Media* m);
|
||||
void update_data();
|
||||
|
||||
private:
|
||||
Media* root_item;
|
||||
};
|
||||
|
||||
#endif // PROJECTMODEL_H
|
||||
+66
-100
@@ -15,13 +15,14 @@
|
||||
#include "ui/sourcetable.h"
|
||||
#include "project/effect.h"
|
||||
#include "project/transition.h"
|
||||
#include "io/media.h"
|
||||
#include "project/footage.h"
|
||||
#include "playback/cacher.h"
|
||||
#include "ui/labelslider.h"
|
||||
#include "ui/viewerwidget.h"
|
||||
#include "project/marker.h"
|
||||
#include "mainwindow.h"
|
||||
#include "io/clipboard.h"
|
||||
#include "project/media.h"
|
||||
#include "debug.h"
|
||||
|
||||
QUndoStack undo_stack;
|
||||
@@ -169,7 +170,7 @@ void SetTimelineInOutCommand::undo() {
|
||||
|
||||
// footage viewer functions
|
||||
if (seq->wrapper_sequence) {
|
||||
Media* m = static_cast<Media*>(seq->clips.at(0)->media);
|
||||
Footage* m = seq->clips.at(0)->media->to_footage();
|
||||
m->using_inout = old_enabled;
|
||||
m->in = old_in;
|
||||
m->out = old_out;
|
||||
@@ -189,7 +190,7 @@ void SetTimelineInOutCommand::redo() {
|
||||
|
||||
// footage viewer functions
|
||||
if (seq->wrapper_sequence) {
|
||||
Media* m = static_cast<Media*>(seq->clips.at(0)->media);
|
||||
Footage* m = seq->clips.at(0)->media->to_footage();
|
||||
m->using_inout = new_enabled;
|
||||
m->in = new_in;
|
||||
m->out = new_out;
|
||||
@@ -340,7 +341,7 @@ void DeleteTransitionCommand::redo() {
|
||||
mainWindow->setWindowModified(true);
|
||||
}
|
||||
|
||||
NewSequenceCommand::NewSequenceCommand(QTreeWidgetItem *s, QTreeWidgetItem* iparent) :
|
||||
NewSequenceCommand::NewSequenceCommand(Media *s, Media* iparent) :
|
||||
seq(s),
|
||||
parent(iparent),
|
||||
done(false),
|
||||
@@ -353,7 +354,7 @@ NewSequenceCommand::~NewSequenceCommand() {
|
||||
|
||||
void NewSequenceCommand::undo() {
|
||||
if (parent == NULL) {
|
||||
panel_project->source_table->takeTopLevelItem(panel_project->source_table->indexOfTopLevelItem(seq));
|
||||
project_model.removeTopLevelItem(seq);
|
||||
} else {
|
||||
parent->removeChild(seq);
|
||||
}
|
||||
@@ -363,45 +364,38 @@ void NewSequenceCommand::undo() {
|
||||
|
||||
void NewSequenceCommand::redo() {
|
||||
if (parent == NULL) {
|
||||
panel_project->source_table->addTopLevelItem(seq);
|
||||
project_model.addTopLevelItem(seq);
|
||||
} else {
|
||||
parent->addChild(seq);
|
||||
parent->appendChild(seq);
|
||||
}
|
||||
done = true;
|
||||
mainWindow->setWindowModified(true);
|
||||
}
|
||||
|
||||
AddMediaCommand::AddMediaCommand(QTreeWidgetItem* iitem, QTreeWidgetItem* iparent) :
|
||||
AddMediaCommand::AddMediaCommand(Media* iitem, Media* iparent) :
|
||||
item(iitem),
|
||||
parent(iparent),
|
||||
done(false),
|
||||
old_project_changed(mainWindow->isWindowModified())
|
||||
{}
|
||||
{
|
||||
if (parent == NULL) parent = project_model.get_root();
|
||||
}
|
||||
|
||||
AddMediaCommand::~AddMediaCommand() {
|
||||
if (!done) {
|
||||
panel_project->delete_media(item);
|
||||
if (item->data(0, Qt::UserRole + 5) != 0) delete reinterpret_cast<MediaThrobber*>(item->data(0, Qt::UserRole + 5).value<quintptr>());
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
void AddMediaCommand::undo() {
|
||||
if (parent == NULL) {
|
||||
panel_project->source_table->takeTopLevelItem(panel_project->source_table->indexOfTopLevelItem(item));
|
||||
} else {
|
||||
parent->removeChild(item);
|
||||
}
|
||||
parent->removeChild(item);
|
||||
done = false;
|
||||
mainWindow->setWindowModified(old_project_changed);
|
||||
}
|
||||
|
||||
void AddMediaCommand::redo() {
|
||||
if (parent == NULL) {
|
||||
panel_project->source_table->addTopLevelItem(item);
|
||||
} else {
|
||||
parent->addChild(item);
|
||||
}
|
||||
parent->appendChild(item);
|
||||
project_model.update_data();
|
||||
|
||||
/* Here we force the source_table to sort itself.
|
||||
*
|
||||
@@ -419,32 +413,33 @@ void AddMediaCommand::redo() {
|
||||
* I guess I'm "supposed" to use a Model–view–viewmodel instead,
|
||||
* which I'll probably have to switch to soon anyway. So perhaps
|
||||
* this will be a non-issue soon.
|
||||
*/
|
||||
|
||||
panel_project->source_table->setSortingEnabled(false);
|
||||
panel_project->source_table->setSortingEnabled(true);
|
||||
panel_project->source_table->setSortingEnabled(true);*/
|
||||
|
||||
done = true;
|
||||
mainWindow->setWindowModified(true);
|
||||
}
|
||||
|
||||
DeleteMediaCommand::DeleteMediaCommand(QTreeWidgetItem* i) :
|
||||
DeleteMediaCommand::DeleteMediaCommand(const QModelIndex& i) :
|
||||
item(i),
|
||||
parent(i.parent()),
|
||||
old_project_changed(mainWindow->isWindowModified())
|
||||
{}
|
||||
|
||||
DeleteMediaCommand::~DeleteMediaCommand() {
|
||||
if (done) {
|
||||
panel_project->delete_media(item);
|
||||
if (item->data(0, Qt::UserRole + 5) != 0) delete reinterpret_cast<MediaThrobber*>(item->data(0, Qt::UserRole + 5).value<quintptr>());
|
||||
delete item;
|
||||
Media* m = static_cast<Media*>(item.internalPointer());
|
||||
delete m;
|
||||
}
|
||||
}
|
||||
|
||||
void DeleteMediaCommand::undo() {
|
||||
if (parent == NULL) {
|
||||
panel_project->source_table->addTopLevelItem(item);
|
||||
Media* m = static_cast<Media*>(item.internalPointer());
|
||||
if (!parent.isValid()) {
|
||||
project_model.addTopLevelItem(m);
|
||||
} else {
|
||||
parent->addChild(item);
|
||||
static_cast<Media*>(parent.internalPointer())->appendChild(m);
|
||||
}
|
||||
|
||||
mainWindow->setWindowModified(old_project_changed);
|
||||
@@ -452,14 +447,14 @@ void DeleteMediaCommand::undo() {
|
||||
}
|
||||
|
||||
void DeleteMediaCommand::redo() {
|
||||
parent = item->parent();
|
||||
|
||||
if (parent == NULL) {
|
||||
panel_project->source_table->takeTopLevelItem(panel_project->source_table->indexOfTopLevelItem(item));
|
||||
Media* m = static_cast<Media*>(item.internalPointer());
|
||||
if (!parent.isValid()) {
|
||||
project_model.removeTopLevelItem(m);
|
||||
} else {
|
||||
parent->removeChild(item);
|
||||
static_cast<Media*>(parent.internalPointer())->removeChild(m);
|
||||
}
|
||||
|
||||
project_model.update_data();
|
||||
mainWindow->setWindowModified(true);
|
||||
done = true;
|
||||
}
|
||||
@@ -601,25 +596,24 @@ void CheckboxCommand::redo() {
|
||||
mainWindow->setWindowModified(true);
|
||||
}
|
||||
|
||||
ReplaceMediaCommand::ReplaceMediaCommand(QTreeWidgetItem* i, QString s) :
|
||||
ReplaceMediaCommand::ReplaceMediaCommand(Media* i, QString s) :
|
||||
item(i),
|
||||
new_filename(s),
|
||||
old_project_changed(mainWindow->isWindowModified())
|
||||
{
|
||||
media = get_footage_from_tree(item);
|
||||
old_filename = media->url;
|
||||
old_filename = item->to_footage()->url;
|
||||
}
|
||||
|
||||
void ReplaceMediaCommand::replace(QString& filename) {
|
||||
// close any clips currently using this media
|
||||
QVector<Sequence*> all_sequences = panel_project->list_all_project_sequences();
|
||||
QVector<Media*> all_sequences = panel_project->list_all_project_sequences();
|
||||
for (int i=0;i<all_sequences.size();i++) {
|
||||
Sequence* s = all_sequences.at(i);
|
||||
Sequence* s = all_sequences.at(i)->to_sequence();
|
||||
for (int j=0;j<s->clips.size();j++) {
|
||||
Clip* c = s->clips.at(j);
|
||||
if (c != NULL && c->media == media && c->open) {
|
||||
if (c != NULL && c->media == item && c->open) {
|
||||
close_clip(c);
|
||||
if (c->media_type == MEDIA_TYPE_FOOTAGE) c->cacher->wait();
|
||||
if (c->media != NULL && c->media->get_type() == MEDIA_TYPE_FOOTAGE) c->cacher->wait();
|
||||
c->replaced = true;
|
||||
}
|
||||
}
|
||||
@@ -643,11 +637,9 @@ void ReplaceMediaCommand::redo() {
|
||||
mainWindow->setWindowModified(true);
|
||||
}
|
||||
|
||||
ReplaceClipMediaCommand::ReplaceClipMediaCommand(void *a, void *b, int c, int d, bool e) :
|
||||
ReplaceClipMediaCommand::ReplaceClipMediaCommand(Media *a, Media *b, bool e) :
|
||||
old_media(a),
|
||||
new_media(b),
|
||||
old_type(c),
|
||||
new_type(d),
|
||||
new_media(b),
|
||||
preserve_clip_ins(e),
|
||||
old_project_changed(mainWindow->isWindowModified())
|
||||
{}
|
||||
@@ -661,7 +653,7 @@ void ReplaceClipMediaCommand::replace(bool undo) {
|
||||
Clip* c = clips.at(i);
|
||||
if (c->open) {
|
||||
close_clip(c);
|
||||
if (c->media_type == MEDIA_TYPE_FOOTAGE) c->cacher->wait();
|
||||
if (c->media != NULL && c->media->get_type() == MEDIA_TYPE_FOOTAGE) c->cacher->wait();
|
||||
}
|
||||
|
||||
if (undo) {
|
||||
@@ -669,16 +661,14 @@ void ReplaceClipMediaCommand::replace(bool undo) {
|
||||
c->clip_in = old_clip_ins.at(i);
|
||||
}
|
||||
|
||||
c->media = old_media;
|
||||
c->media_type = old_type;
|
||||
c->media = old_media;
|
||||
} else {
|
||||
if (!preserve_clip_ins) {
|
||||
old_clip_ins.append(c->clip_in);
|
||||
c->clip_in = 0;
|
||||
}
|
||||
|
||||
c->media = new_media;
|
||||
c->media_type = new_type;
|
||||
c->media = new_media;
|
||||
}
|
||||
|
||||
c->replaced = true;
|
||||
@@ -695,6 +685,7 @@ void ReplaceClipMediaCommand::undo() {
|
||||
void ReplaceClipMediaCommand::redo() {
|
||||
replace(false);
|
||||
|
||||
update_ui(true);
|
||||
mainWindow->setWindowModified(true);
|
||||
}
|
||||
|
||||
@@ -737,61 +728,40 @@ MediaMove::MediaMove(SourceTable *s) : table(s), old_project_changed(mainWindow-
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
for (int i=0;i<items.size();i++) {
|
||||
if (froms.at(i) == NULL) {
|
||||
table->addTopLevelItem(items.at(i));
|
||||
} else {
|
||||
froms.at(i)->addChild(items.at(i));
|
||||
}
|
||||
}
|
||||
to->removeChild(items.at(i));
|
||||
froms.at(i)->appendChild(items.at(i));
|
||||
}
|
||||
mainWindow->setWindowModified(old_project_changed);
|
||||
}
|
||||
|
||||
void MediaMove::redo() {
|
||||
if (to == NULL) to = project_model.get_root();
|
||||
froms.resize(items.size());
|
||||
for (int i=0;i<items.size();i++) {
|
||||
QTreeWidgetItem* parent = items.at(i)->parent();
|
||||
Media* parent = items.at(i)->parentItem();
|
||||
froms[i] = 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));
|
||||
}
|
||||
}
|
||||
for (int i=0;i<items.size();i++) {
|
||||
if (to == NULL) {
|
||||
table->addTopLevelItem(items.at(i));
|
||||
} else {
|
||||
to->addChild(items.at(i));
|
||||
}
|
||||
}
|
||||
parent->removeChild(items.at(i));
|
||||
to->appendChild(items.at(i));
|
||||
}
|
||||
project_model.update_data();
|
||||
mainWindow->setWindowModified(true);
|
||||
}
|
||||
|
||||
MediaRename::MediaRename() : done(true), old_project_changed(mainWindow->isWindowModified()) {}
|
||||
MediaRename::MediaRename(Media* iitem, QString ito) :
|
||||
item(iitem),
|
||||
from(iitem->get_name()),
|
||||
to(ito),
|
||||
old_project_changed(mainWindow->isWindowModified())
|
||||
{}
|
||||
|
||||
void MediaRename::undo() {
|
||||
item->setText(0, from);
|
||||
done = false;
|
||||
mainWindow->setWindowModified(old_project_changed);
|
||||
item->set_name(from);
|
||||
mainWindow->setWindowModified(old_project_changed);
|
||||
}
|
||||
|
||||
void MediaRename::redo() {
|
||||
if (!done) {
|
||||
item->setText(0, to);
|
||||
}
|
||||
mainWindow->setWindowModified(true);
|
||||
item->set_name(to);
|
||||
mainWindow->setWindowModified(true);
|
||||
}
|
||||
|
||||
KeyframeMove::KeyframeMove() : old_project_changed(mainWindow->isWindowModified()) {}
|
||||
@@ -1138,7 +1108,7 @@ void SetEnableCommand::redo() {
|
||||
mainWindow->setWindowModified(true);
|
||||
}
|
||||
|
||||
EditSequenceCommand::EditSequenceCommand(QTreeWidgetItem* i, Sequence *s) :
|
||||
EditSequenceCommand::EditSequenceCommand(Media* i, Sequence *s) :
|
||||
item(i),
|
||||
seq(s),
|
||||
old_project_changed(mainWindow->isWindowModified()),
|
||||
@@ -1175,11 +1145,8 @@ void EditSequenceCommand::redo() {
|
||||
}
|
||||
|
||||
void EditSequenceCommand::update() {
|
||||
// update name
|
||||
item->setText(0, seq->name);
|
||||
|
||||
// update tooltip
|
||||
set_sequence_of_tree(item, seq);
|
||||
item->set_sequence(seq);
|
||||
|
||||
for (int i=0;i<seq->clips.size();i++) {
|
||||
// TODO shift in/out/clipin points to match new frame rate
|
||||
@@ -1237,9 +1204,8 @@ void CloseAllClipsCommand::redo() {
|
||||
closeActiveClips(sequence, true);
|
||||
}
|
||||
|
||||
UpdateFootageTooltip::UpdateFootageTooltip(QTreeWidgetItem *i, Media *m) :
|
||||
item(i),
|
||||
media(m)
|
||||
UpdateFootageTooltip::UpdateFootageTooltip(Media *i) :
|
||||
item(i)
|
||||
{}
|
||||
|
||||
void UpdateFootageTooltip::undo() {
|
||||
@@ -1247,7 +1213,7 @@ void UpdateFootageTooltip::undo() {
|
||||
}
|
||||
|
||||
void UpdateFootageTooltip::redo() {
|
||||
update_footage_tooltip(item, media);
|
||||
item->update_tooltip();
|
||||
}
|
||||
|
||||
MoveEffectCommand::MoveEffectCommand() :
|
||||
|
||||
+31
-36
@@ -1,7 +1,7 @@
|
||||
#ifndef UNDO_H
|
||||
#define UNDO_H
|
||||
|
||||
class QTreeWidgetItem;
|
||||
class Media;
|
||||
class QCheckBox;
|
||||
class LabelSlider;
|
||||
class Effect;
|
||||
@@ -12,7 +12,7 @@ class Transition;
|
||||
class EffectGizmo;
|
||||
struct Clip;
|
||||
struct Sequence;
|
||||
struct Media;
|
||||
struct Footage;
|
||||
struct EffectMeta;
|
||||
|
||||
#include "project/marker.h"
|
||||
@@ -166,39 +166,39 @@ private:
|
||||
|
||||
class NewSequenceCommand : public QUndoCommand {
|
||||
public:
|
||||
NewSequenceCommand(QTreeWidgetItem *s, QTreeWidgetItem* iparent);
|
||||
NewSequenceCommand(Media *s, Media* iparent);
|
||||
~NewSequenceCommand();
|
||||
void undo();
|
||||
void redo();
|
||||
private:
|
||||
QTreeWidgetItem* seq;
|
||||
QTreeWidgetItem* parent;
|
||||
Media* seq;
|
||||
Media* parent;
|
||||
bool done;
|
||||
bool old_project_changed;
|
||||
};
|
||||
|
||||
class AddMediaCommand : public QUndoCommand {
|
||||
public:
|
||||
AddMediaCommand(QTreeWidgetItem* iitem, QTreeWidgetItem* iparent);
|
||||
AddMediaCommand(Media* iitem, Media* iparent);
|
||||
~AddMediaCommand();
|
||||
void undo();
|
||||
void redo();
|
||||
private:
|
||||
QTreeWidgetItem* item;
|
||||
QTreeWidgetItem* parent;
|
||||
Media* item;
|
||||
Media* parent;
|
||||
bool done;
|
||||
bool old_project_changed;
|
||||
};
|
||||
|
||||
class DeleteMediaCommand : public QUndoCommand {
|
||||
public:
|
||||
DeleteMediaCommand(QTreeWidgetItem* i);
|
||||
DeleteMediaCommand(const QModelIndex& i);
|
||||
~DeleteMediaCommand();
|
||||
void undo();
|
||||
void redo();
|
||||
private:
|
||||
QTreeWidgetItem* item;
|
||||
QTreeWidgetItem* parent;
|
||||
const QModelIndex& item;
|
||||
const QModelIndex& parent;
|
||||
bool old_project_changed;
|
||||
bool done;
|
||||
};
|
||||
@@ -258,29 +258,26 @@ private:
|
||||
|
||||
class ReplaceMediaCommand : public QUndoCommand {
|
||||
public:
|
||||
ReplaceMediaCommand(QTreeWidgetItem*, QString);
|
||||
ReplaceMediaCommand(Media*, QString);
|
||||
void undo();
|
||||
void redo();
|
||||
private:
|
||||
QTreeWidgetItem *item;
|
||||
Media *item;
|
||||
QString old_filename;
|
||||
QString new_filename;
|
||||
bool old_project_changed;
|
||||
Media* media;
|
||||
bool old_project_changed;
|
||||
void replace(QString& filename);
|
||||
};
|
||||
|
||||
class ReplaceClipMediaCommand : public QUndoCommand {
|
||||
public:
|
||||
ReplaceClipMediaCommand(void*, void*, int, int, bool);
|
||||
ReplaceClipMediaCommand(Media *, Media *, bool);
|
||||
void undo();
|
||||
void redo();
|
||||
QVector<Clip*> clips;
|
||||
private:
|
||||
void* old_media;
|
||||
void* new_media;
|
||||
int old_type;
|
||||
int new_type;
|
||||
Media* old_media;
|
||||
Media* new_media;
|
||||
bool preserve_clip_ins;
|
||||
bool old_project_changed;
|
||||
QVector<int> old_clip_ins;
|
||||
@@ -304,27 +301,26 @@ private:
|
||||
class MediaMove : public QUndoCommand {
|
||||
public:
|
||||
MediaMove(SourceTable* s);
|
||||
QVector<QTreeWidgetItem*> items;
|
||||
QTreeWidgetItem* to;
|
||||
QVector<Media*> items;
|
||||
Media* to;
|
||||
void undo();
|
||||
void redo();
|
||||
private:
|
||||
QVector<QTreeWidgetItem*> froms;
|
||||
QVector<Media*> froms;
|
||||
SourceTable* table;
|
||||
bool old_project_changed;
|
||||
};
|
||||
|
||||
class MediaRename : public QUndoCommand {
|
||||
public:
|
||||
MediaRename();
|
||||
QTreeWidgetItem* item;
|
||||
QString from;
|
||||
QString to;
|
||||
void undo();
|
||||
void redo();
|
||||
MediaRename(Media* iitem, QString to);
|
||||
void undo();
|
||||
void redo();
|
||||
private:
|
||||
bool done;
|
||||
bool old_project_changed;
|
||||
bool old_project_changed;
|
||||
Media* item;
|
||||
QString from;
|
||||
QString to;
|
||||
};
|
||||
|
||||
class KeyframeMove : public QUndoCommand {
|
||||
@@ -486,7 +482,7 @@ private:
|
||||
|
||||
class EditSequenceCommand : public QUndoCommand {
|
||||
public:
|
||||
EditSequenceCommand(QTreeWidgetItem *i, Sequence* s);
|
||||
EditSequenceCommand(Media *i, Sequence* s);
|
||||
void undo();
|
||||
void redo();
|
||||
void update();
|
||||
@@ -498,7 +494,7 @@ public:
|
||||
int audio_frequency;
|
||||
int audio_layout;
|
||||
private:
|
||||
QTreeWidgetItem* item;
|
||||
Media* item;
|
||||
Sequence* seq;
|
||||
bool old_project_changed;
|
||||
|
||||
@@ -542,12 +538,11 @@ public:
|
||||
|
||||
class UpdateFootageTooltip : public QUndoCommand {
|
||||
public:
|
||||
UpdateFootageTooltip(QTreeWidgetItem* i, Media* m);
|
||||
UpdateFootageTooltip(Media* i);
|
||||
void undo();
|
||||
void redo();
|
||||
private:
|
||||
QTreeWidgetItem* item;
|
||||
Media* media;
|
||||
Media* item;
|
||||
};
|
||||
|
||||
class MoveEffectCommand : public QUndoCommand {
|
||||
|
||||
Reference in New Issue
Block a user