folder support added
This commit is contained in:
@@ -4,8 +4,8 @@
|
|||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QtMath>
|
#include <QtMath>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "playback/audio.h"
|
|
||||||
#include "ui/labelslider.h"
|
#include "ui/labelslider.h"
|
||||||
#include "ui/collapsiblewidget.h"
|
#include "ui/collapsiblewidget.h"
|
||||||
|
|
||||||
|
|||||||
+1
-3
@@ -6,9 +6,7 @@ extern "C" {
|
|||||||
#include <libavformat/avformat.h>
|
#include <libavformat/avformat.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
Media::Media() {
|
Media::Media() {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Media::~Media() {
|
Media::~Media() {
|
||||||
for (int i=0;i<video_tracks.size();i++) {
|
for (int i=0;i<video_tracks.size();i++) {
|
||||||
|
|||||||
+1
-8
@@ -8,11 +8,6 @@
|
|||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
|
|
||||||
#define MEDIA_TYPE_FOOTAGE 0
|
|
||||||
#define MEDIA_TYPE_SEQUENCE 1
|
|
||||||
#define MEDIA_TYPE_FOLDER 2
|
|
||||||
#define MEDIA_TYPE_SOLID 3
|
|
||||||
|
|
||||||
struct Sequence;
|
struct Sequence;
|
||||||
|
|
||||||
struct MediaStream {
|
struct MediaStream {
|
||||||
@@ -34,12 +29,10 @@ struct Media
|
|||||||
~Media();
|
~Media();
|
||||||
|
|
||||||
QString url;
|
QString url;
|
||||||
QString name;
|
QString name;
|
||||||
char type;
|
|
||||||
int64_t length;
|
int64_t length;
|
||||||
QVector<MediaStream*> video_tracks;
|
QVector<MediaStream*> video_tracks;
|
||||||
QVector<MediaStream*> audio_tracks;
|
QVector<MediaStream*> audio_tracks;
|
||||||
Sequence* sequence;
|
|
||||||
int save_id;
|
int save_id;
|
||||||
long get_length_in_frames(float frame_rate);
|
long get_length_in_frames(float frame_rate);
|
||||||
MediaStream* get_stream_from_file_index(int index);
|
MediaStream* get_stream_from_file_index(int index);
|
||||||
|
|||||||
+143
-151
@@ -26,170 +26,162 @@ PreviewGenerator::PreviewGenerator(QObject* parent) : QThread(parent) {
|
|||||||
#define WAVEFORM_RESOLUTION 64
|
#define WAVEFORM_RESOLUTION 64
|
||||||
|
|
||||||
void PreviewGenerator::run() {
|
void PreviewGenerator::run() {
|
||||||
if (media == NULL) {
|
Q_ASSERT(media != NULL);
|
||||||
qDebug() << "[ERROR] No media was set for preview generation";
|
|
||||||
} else {
|
|
||||||
if (media->type == MEDIA_TYPE_SEQUENCE) {
|
|
||||||
qDebug() << "[ERROR] Cannot run preview generation on a sequence";
|
|
||||||
} else {
|
|
||||||
SwsContext* sws_ctx;
|
|
||||||
SwrContext* swr_ctx;
|
|
||||||
AVFrame* temp_frame = av_frame_alloc();
|
|
||||||
AVCodecContext** codec_ctx = new AVCodecContext* [fmt_ctx->nb_streams];
|
|
||||||
for (unsigned int i=0;i<fmt_ctx->nb_streams;i++) {
|
|
||||||
codec_ctx[i] = NULL;
|
|
||||||
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
|
||||||
AVCodec* codec = avcodec_find_decoder(fmt_ctx->streams[i]->codecpar->codec_id);
|
|
||||||
codec_ctx[i] = avcodec_alloc_context3(codec);
|
|
||||||
avcodec_parameters_to_context(codec_ctx[i], fmt_ctx->streams[i]->codecpar);
|
|
||||||
avcodec_open2(codec_ctx[i], codec, NULL);
|
|
||||||
|
|
||||||
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && codec_ctx[i]->channel_layout == 0) {
|
SwsContext* sws_ctx;
|
||||||
codec_ctx[i]->channel_layout = guess_layout_from_channels(fmt_ctx->streams[i]->codecpar->channels);
|
SwrContext* swr_ctx;
|
||||||
}
|
AVFrame* temp_frame = av_frame_alloc();
|
||||||
|
AVCodecContext** codec_ctx = new AVCodecContext* [fmt_ctx->nb_streams];
|
||||||
|
for (unsigned int i=0;i<fmt_ctx->nb_streams;i++) {
|
||||||
|
codec_ctx[i] = NULL;
|
||||||
|
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||||
|
AVCodec* codec = avcodec_find_decoder(fmt_ctx->streams[i]->codecpar->codec_id);
|
||||||
|
codec_ctx[i] = avcodec_alloc_context3(codec);
|
||||||
|
avcodec_parameters_to_context(codec_ctx[i], fmt_ctx->streams[i]->codecpar);
|
||||||
|
avcodec_open2(codec_ctx[i], codec, NULL);
|
||||||
|
|
||||||
|
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && codec_ctx[i]->channel_layout == 0) {
|
||||||
|
codec_ctx[i]->channel_layout = guess_layout_from_channels(fmt_ctx->streams[i]->codecpar->channels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AVPacket packet;
|
||||||
|
bool done = true;
|
||||||
|
|
||||||
|
bool end_of_file = false;
|
||||||
|
|
||||||
|
// get the ball rolling
|
||||||
|
av_read_frame(fmt_ctx, &packet);
|
||||||
|
avcodec_send_packet(codec_ctx[packet.stream_index], &packet);
|
||||||
|
|
||||||
|
while (!end_of_file) {
|
||||||
|
while (codec_ctx[packet.stream_index] == NULL || avcodec_receive_frame(codec_ctx[packet.stream_index], temp_frame) == AVERROR(EAGAIN)) {
|
||||||
|
av_packet_unref(&packet);
|
||||||
|
int read_ret = av_read_frame(fmt_ctx, &packet);
|
||||||
|
if (read_ret < 0) {
|
||||||
|
end_of_file = true;
|
||||||
|
if (read_ret != AVERROR_EOF) qDebug() << "[ERROR] Failed to read packet for preview generation";
|
||||||
|
break;
|
||||||
|
} else if (codec_ctx[packet.stream_index] != NULL) {
|
||||||
|
int send_ret = avcodec_send_packet(codec_ctx[packet.stream_index], &packet);
|
||||||
|
if (send_ret < 0) {
|
||||||
|
qDebug() << "[ERROR] Failed to send packet for preview generation - aborting";
|
||||||
|
end_of_file = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AVPacket packet;
|
}
|
||||||
bool done = true;
|
if (!end_of_file) {
|
||||||
|
MediaStream* s = media->get_stream_from_file_index(packet.stream_index);
|
||||||
|
if (s != NULL && !s->preview_done) {
|
||||||
|
if (fmt_ctx->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||||
|
int dstH = 120;
|
||||||
|
int dstW = dstH * ((float)temp_frame->width/(float)temp_frame->height);
|
||||||
|
uint8_t* data = new uint8_t[dstW*dstH*3];
|
||||||
|
|
||||||
bool end_of_file = false;
|
sws_ctx = sws_getContext(
|
||||||
|
temp_frame->width,
|
||||||
|
temp_frame->height,
|
||||||
|
static_cast<AVPixelFormat>(temp_frame->format),
|
||||||
|
dstW,
|
||||||
|
dstH,
|
||||||
|
static_cast<AVPixelFormat>(AV_PIX_FMT_RGB24),
|
||||||
|
SWS_FAST_BILINEAR,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
// get the ball rolling
|
int linesize[AV_NUM_DATA_POINTERS];
|
||||||
av_read_frame(fmt_ctx, &packet);
|
linesize[0] = dstW*3;
|
||||||
avcodec_send_packet(codec_ctx[packet.stream_index], &packet);
|
sws_scale(sws_ctx, temp_frame->data, temp_frame->linesize, 0, temp_frame->height, &data, linesize);
|
||||||
|
|
||||||
while (!end_of_file) {
|
s->video_preview = QImage(data, dstW, dstH, linesize[0], QImage::Format_RGB888);
|
||||||
while (codec_ctx[packet.stream_index] == NULL || avcodec_receive_frame(codec_ctx[packet.stream_index], temp_frame) == AVERROR(EAGAIN)) {
|
|
||||||
av_packet_unref(&packet);
|
// delete [] data;
|
||||||
int read_ret = av_read_frame(fmt_ctx, &packet);
|
|
||||||
if (read_ret < 0) {
|
s->preview_done = true;
|
||||||
end_of_file = true;
|
|
||||||
if (read_ret != AVERROR_EOF) qDebug() << "[ERROR] Failed to read packet for preview generation";
|
sws_freeContext(sws_ctx);
|
||||||
break;
|
|
||||||
} else if (codec_ctx[packet.stream_index] != NULL) {
|
avcodec_close(codec_ctx[packet.stream_index]);
|
||||||
int send_ret = avcodec_send_packet(codec_ctx[packet.stream_index], &packet);
|
codec_ctx[packet.stream_index] = NULL;
|
||||||
if (send_ret < 0) {
|
} else if (fmt_ctx->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||||
qDebug() << "[ERROR] Failed to send packet for preview generation - aborting";
|
int interval = qFloor((temp_frame->sample_rate/WAVEFORM_RESOLUTION)/4)*4;
|
||||||
end_of_file = true;
|
|
||||||
|
AVFrame* swr_frame = av_frame_alloc();
|
||||||
|
swr_frame->channel_layout = temp_frame->channel_layout;
|
||||||
|
swr_frame->sample_rate = temp_frame->sample_rate;
|
||||||
|
swr_frame->format = AV_SAMPLE_FMT_S16;
|
||||||
|
|
||||||
|
swr_ctx = swr_alloc_set_opts(
|
||||||
|
NULL,
|
||||||
|
temp_frame->channel_layout,
|
||||||
|
static_cast<AVSampleFormat>(swr_frame->format),
|
||||||
|
temp_frame->sample_rate,
|
||||||
|
temp_frame->channel_layout,
|
||||||
|
static_cast<AVSampleFormat>(temp_frame->format),
|
||||||
|
temp_frame->sample_rate,
|
||||||
|
0,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
swr_init(swr_ctx);
|
||||||
|
|
||||||
|
swr_convert_frame(swr_ctx, swr_frame, temp_frame);
|
||||||
|
|
||||||
|
int channel_skip = swr_frame->channels * 2;
|
||||||
|
for (int i=0;i<swr_frame->nb_samples;i+=interval) {
|
||||||
|
for (int j=0;j<swr_frame->channels;j++) {
|
||||||
|
qint16 min = 0;
|
||||||
|
qint16 max = 0;
|
||||||
|
for (int k=j*2;k<interval;k+=channel_skip) {
|
||||||
|
qint16 sample = ((swr_frame->data[0][i+k+1] << 8) | swr_frame->data[0][i+k]);
|
||||||
|
if (sample > max) {
|
||||||
|
max = sample;
|
||||||
|
} else if (sample < min) {
|
||||||
|
min = sample;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
min /= 256;
|
||||||
|
max /= 256;
|
||||||
|
s->audio_preview.append(min);
|
||||||
|
s->audio_preview.append(max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
swr_free(&swr_ctx);
|
||||||
|
av_frame_free(&swr_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if we've got all our previews
|
||||||
|
if (media->audio_tracks.size() == 0) {
|
||||||
|
done = true;
|
||||||
|
for (int i=0;i<media->video_tracks.size();i++) {
|
||||||
|
if (!media->video_tracks.at(i)->preview_done) {
|
||||||
|
done = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (done) {
|
||||||
if (!end_of_file) {
|
end_of_file = true;
|
||||||
MediaStream* s = media->get_stream_from_file_index(packet.stream_index);
|
break;
|
||||||
if (s != NULL && !s->preview_done) {
|
|
||||||
if (fmt_ctx->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
|
||||||
int dstH = 120;
|
|
||||||
int dstW = dstH * ((float)temp_frame->width/(float)temp_frame->height);
|
|
||||||
uint8_t* data = new uint8_t[dstW*dstH*3];
|
|
||||||
|
|
||||||
sws_ctx = sws_getContext(
|
|
||||||
temp_frame->width,
|
|
||||||
temp_frame->height,
|
|
||||||
static_cast<AVPixelFormat>(temp_frame->format),
|
|
||||||
dstW,
|
|
||||||
dstH,
|
|
||||||
static_cast<AVPixelFormat>(AV_PIX_FMT_RGB24),
|
|
||||||
SWS_FAST_BILINEAR,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
int linesize[AV_NUM_DATA_POINTERS];
|
|
||||||
linesize[0] = dstW*3;
|
|
||||||
sws_scale(sws_ctx, temp_frame->data, temp_frame->linesize, 0, temp_frame->height, &data, linesize);
|
|
||||||
|
|
||||||
s->video_preview = QImage(data, dstW, dstH, linesize[0], QImage::Format_RGB888);
|
|
||||||
|
|
||||||
// delete [] data;
|
|
||||||
|
|
||||||
s->preview_done = true;
|
|
||||||
|
|
||||||
sws_freeContext(sws_ctx);
|
|
||||||
|
|
||||||
avcodec_close(codec_ctx[packet.stream_index]);
|
|
||||||
codec_ctx[packet.stream_index] = NULL;
|
|
||||||
} else if (fmt_ctx->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
|
||||||
int interval = qFloor((temp_frame->sample_rate/WAVEFORM_RESOLUTION)/4)*4;
|
|
||||||
|
|
||||||
AVFrame* swr_frame = av_frame_alloc();
|
|
||||||
swr_frame->channel_layout = temp_frame->channel_layout;
|
|
||||||
swr_frame->sample_rate = temp_frame->sample_rate;
|
|
||||||
swr_frame->format = AV_SAMPLE_FMT_S16;
|
|
||||||
|
|
||||||
swr_ctx = swr_alloc_set_opts(
|
|
||||||
NULL,
|
|
||||||
temp_frame->channel_layout,
|
|
||||||
static_cast<AVSampleFormat>(swr_frame->format),
|
|
||||||
temp_frame->sample_rate,
|
|
||||||
temp_frame->channel_layout,
|
|
||||||
static_cast<AVSampleFormat>(temp_frame->format),
|
|
||||||
temp_frame->sample_rate,
|
|
||||||
0,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
swr_init(swr_ctx);
|
|
||||||
|
|
||||||
swr_convert_frame(swr_ctx, swr_frame, temp_frame);
|
|
||||||
|
|
||||||
int channel_skip = swr_frame->channels * 2;
|
|
||||||
for (int i=0;i<swr_frame->nb_samples;i+=interval) {
|
|
||||||
for (int j=0;j<swr_frame->channels;j++) {
|
|
||||||
qint16 min = 0;
|
|
||||||
qint16 max = 0;
|
|
||||||
for (int k=j*2;k<interval;k+=channel_skip) {
|
|
||||||
qint16 sample = ((swr_frame->data[0][i+k+1] << 8) | swr_frame->data[0][i+k]);
|
|
||||||
if (sample > max) {
|
|
||||||
max = sample;
|
|
||||||
} else if (sample < min) {
|
|
||||||
min = sample;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
min /= 256;
|
|
||||||
max /= 256;
|
|
||||||
s->audio_preview.append(min);
|
|
||||||
s->audio_preview.append(max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
swr_free(&swr_ctx);
|
|
||||||
av_frame_free(&swr_frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if we've got all our previews
|
|
||||||
if (media->audio_tracks.size() == 0) {
|
|
||||||
done = true;
|
|
||||||
for (int i=0;i<media->video_tracks.size();i++) {
|
|
||||||
if (!media->video_tracks.at(i)->preview_done) {
|
|
||||||
done = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (done) {
|
|
||||||
end_of_file = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
av_packet_unref(&packet);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i=0;i<media->audio_tracks.size();i++) {
|
av_packet_unref(&packet);
|
||||||
media->audio_tracks.at(i)->preview_done = true;
|
|
||||||
}
|
|
||||||
av_frame_free(&temp_frame);
|
|
||||||
for (unsigned int i=0;i<fmt_ctx->nb_streams;i++) {
|
|
||||||
if (codec_ctx[i] != NULL) {
|
|
||||||
avcodec_close(codec_ctx[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete [] codec_ctx;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (int i=0;i<media->audio_tracks.size();i++) {
|
||||||
if (fmt_ctx != NULL) {
|
media->audio_tracks.at(i)->preview_done = true;
|
||||||
avformat_close_input(&fmt_ctx);
|
|
||||||
}
|
}
|
||||||
|
av_frame_free(&temp_frame);
|
||||||
|
for (unsigned int i=0;i<fmt_ctx->nb_streams;i++) {
|
||||||
|
if (codec_ctx[i] != NULL) {
|
||||||
|
avcodec_close(codec_ctx[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete [] codec_ctx;
|
||||||
|
|
||||||
|
avformat_close_input(&fmt_ctx);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QCloseEvent>
|
||||||
|
|
||||||
#define OLIVE_FILE_FILTER "Olive Project (*.ove)"
|
#define OLIVE_FILE_FILTER "Olive Project (*.ove)"
|
||||||
|
|
||||||
@@ -304,6 +305,14 @@ bool MainWindow::can_close_project() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::closeEvent(QCloseEvent *e) {
|
||||||
|
if (can_close_project()) {
|
||||||
|
e->accept();
|
||||||
|
} else {
|
||||||
|
e->ignore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::on_action_Save_Project_triggered()
|
void MainWindow::on_action_Save_Project_triggered()
|
||||||
{
|
{
|
||||||
save_project();
|
save_project();
|
||||||
@@ -531,3 +540,8 @@ void MainWindow::on_actionSlide_Tool_triggered()
|
|||||||
{
|
{
|
||||||
if (panel_timeline->focused()) panel_timeline->ui->toolSlideButton->click();
|
if (panel_timeline->focused()) panel_timeline->ui->toolSlideButton->click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionFolder_triggered()
|
||||||
|
{
|
||||||
|
panel_project->new_folder();
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ public:
|
|||||||
explicit MainWindow(QWidget *parent = 0);
|
explicit MainWindow(QWidget *parent = 0);
|
||||||
~MainWindow();
|
~MainWindow();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void closeEvent(QCloseEvent *);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_action_Import_triggered();
|
void on_action_Import_triggered();
|
||||||
|
|
||||||
@@ -139,6 +142,8 @@ private slots:
|
|||||||
|
|
||||||
void on_actionSlide_Tool_triggered();
|
void on_actionSlide_Tool_triggered();
|
||||||
|
|
||||||
|
void on_actionFolder_triggered();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MainWindow *ui;
|
Ui::MainWindow *ui;
|
||||||
void setup_layout();
|
void setup_layout();
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
<addaction name="actionProject"/>
|
<addaction name="actionProject"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionSequence"/>
|
<addaction name="actionSequence"/>
|
||||||
|
<addaction name="actionFolder"/>
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="menu_New"/>
|
<addaction name="menu_New"/>
|
||||||
<addaction name="action_Open_Project"/>
|
<addaction name="action_Open_Project"/>
|
||||||
@@ -583,6 +584,11 @@
|
|||||||
<string>U</string>
|
<string>U</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionFolder">
|
||||||
|
<property name="text">
|
||||||
|
<string>Folder</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<resources>
|
<resources>
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE QtCreatorProject>
|
<!DOCTYPE QtCreatorProject>
|
||||||
<!-- Written by QtCreator 4.6.2, 2018-07-10T01:01:52. -->
|
<!-- Written by QtCreator 4.6.2, 2018-07-10T13:36:23. -->
|
||||||
<qtcreator>
|
<qtcreator>
|
||||||
<data>
|
<data>
|
||||||
<variable>EnvironmentId</variable>
|
<variable>EnvironmentId</variable>
|
||||||
|
|||||||
+74
-39
@@ -38,7 +38,7 @@ Project::Project(QWidget *parent) :
|
|||||||
ui(new Ui::Project)
|
ui(new Ui::Project)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
source_table = ui->treeWidget;
|
||||||
connect(ui->treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(rename_media(QTreeWidgetItem*,int)));
|
connect(ui->treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(rename_media(QTreeWidgetItem*,int)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,35 +70,30 @@ QString Project::get_next_sequence_name() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Project::rename_media(QTreeWidgetItem* item, int column) {
|
void Project::rename_media(QTreeWidgetItem* item, int column) {
|
||||||
Media* m = get_media_from_tree(item);
|
int type = get_type_from_tree(item);
|
||||||
m->name = item->text(column);
|
QString n = item->text(column);
|
||||||
if (m->type == MEDIA_TYPE_SEQUENCE) {
|
switch (type) {
|
||||||
m->sequence->name = m->name;
|
case MEDIA_TYPE_FOOTAGE: get_media_from_tree(item)->name = n; break;
|
||||||
|
case MEDIA_TYPE_SEQUENCE: get_sequence_from_tree(item)->name = n; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Project::duplicate_selected() {
|
void Project::duplicate_selected() {
|
||||||
QList<QTreeWidgetItem*> items = ui->treeWidget->selectedItems();
|
QList<QTreeWidgetItem*> items = ui->treeWidget->selectedItems();
|
||||||
for (int i=0;i<items.size();i++) {
|
for (int i=0;i<items.size();i++) {
|
||||||
Media* m = get_media_from_tree(items.at(i));
|
int type = get_type_from_tree(items.at(i));
|
||||||
if (m->type == MEDIA_TYPE_SEQUENCE) {
|
if (type == MEDIA_TYPE_SEQUENCE) {
|
||||||
new_sequence(m->sequence->copy(), false);
|
new_sequence(get_sequence_from_tree(items.at(i))->copy(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Project::new_sequence(Sequence *s, bool open) {
|
void Project::new_sequence(Sequence *s, bool open) {
|
||||||
Media* m = new Media();
|
QTreeWidgetItem* item = new_item();
|
||||||
m->type = MEDIA_TYPE_SEQUENCE;
|
|
||||||
m->sequence = s;
|
|
||||||
|
|
||||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
|
||||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
|
||||||
item->setText(0, s->name);
|
item->setText(0, s->name);
|
||||||
set_media_of_tree(item, m);
|
set_sequence_of_tree(item, s);
|
||||||
|
|
||||||
ui->treeWidget->addTopLevelItem(item);
|
ui->treeWidget->addTopLevelItem(item);
|
||||||
source_table = ui->treeWidget;
|
|
||||||
|
|
||||||
project_changed = true;
|
project_changed = true;
|
||||||
|
|
||||||
@@ -128,7 +123,6 @@ Media* Project::import_file(QString file) {
|
|||||||
av_dump_format(pFormatCtx, 0, filename, 0);
|
av_dump_format(pFormatCtx, 0, filename, 0);
|
||||||
|
|
||||||
m = new Media();
|
m = new Media();
|
||||||
m->type = MEDIA_TYPE_FOOTAGE;
|
|
||||||
m->url = file;
|
m->url = file;
|
||||||
m->name = file.mid(file.lastIndexOf('/')+1);
|
m->name = file.mid(file.lastIndexOf('/')+1);
|
||||||
|
|
||||||
@@ -155,8 +149,7 @@ Media* Project::import_file(QString file) {
|
|||||||
}
|
}
|
||||||
m->length = pFormatCtx->duration;
|
m->length = pFormatCtx->duration;
|
||||||
|
|
||||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
QTreeWidgetItem* item = new_item();
|
||||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
|
||||||
if (m->video_tracks.size() == 0) {
|
if (m->video_tracks.size() == 0) {
|
||||||
item->setIcon(0, QIcon(":/icons/audiosource.png"));
|
item->setIcon(0, QIcon(":/icons/audiosource.png"));
|
||||||
} else {
|
} else {
|
||||||
@@ -169,23 +162,39 @@ Media* Project::import_file(QString file) {
|
|||||||
ui->treeWidget->addTopLevelItem(item);
|
ui->treeWidget->addTopLevelItem(item);
|
||||||
|
|
||||||
project_changed = true;
|
project_changed = true;
|
||||||
|
|
||||||
|
// generate waveform/thumbnail in another thread
|
||||||
|
PreviewGenerator* pg = new PreviewGenerator();
|
||||||
|
pg->fmt_ctx = pFormatCtx; // cleaned up in PG
|
||||||
|
pg->media = m;
|
||||||
|
connect(pg, SIGNAL(finished()), pg, SLOT(deleteLater()));
|
||||||
|
pg->start(QThread::LowPriority);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PreviewGenerator* pg = new PreviewGenerator();
|
|
||||||
pg->fmt_ctx = pFormatCtx; // cleaned up in PG
|
|
||||||
pg->media = m;
|
|
||||||
connect(pg, SIGNAL(finished()), pg, SLOT(deleteLater()));
|
|
||||||
pg->start(QThread::LowPriority);
|
|
||||||
|
|
||||||
delete [] filename;
|
delete [] filename;
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QTreeWidgetItem* Project::new_item() {
|
||||||
|
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||||
|
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
bool Project::is_focused() {
|
bool Project::is_focused() {
|
||||||
return ui->treeWidget->hasFocus();
|
return ui->treeWidget->hasFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Project::new_folder() {
|
||||||
|
QTreeWidgetItem* item = new_item();
|
||||||
|
item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
|
||||||
|
item->setText(0, "New Folder");
|
||||||
|
set_item_to_folder(item);
|
||||||
|
ui->treeWidget->addTopLevelItem(item);
|
||||||
|
project_changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
void Project::delete_selected_media() {
|
void Project::delete_selected_media() {
|
||||||
QList<QTreeWidgetItem*> items = ui->treeWidget->selectedItems();
|
QList<QTreeWidgetItem*> items = ui->treeWidget->selectedItems();
|
||||||
bool remove = true;
|
bool remove = true;
|
||||||
@@ -193,8 +202,9 @@ void Project::delete_selected_media() {
|
|||||||
|
|
||||||
// check if media is in use
|
// check if media is in use
|
||||||
for (int i=0;i<items.size();i++) {
|
for (int i=0;i<items.size();i++) {
|
||||||
Media* m = get_media_from_tree(items.at(i));
|
QTreeWidgetItem* item = items.at(i);
|
||||||
if (m->type == MEDIA_TYPE_FOOTAGE && sequence != NULL) {
|
Media* m = get_media_from_tree(item);
|
||||||
|
if (get_type_from_tree(item) == MEDIA_TYPE_FOOTAGE && sequence != NULL) {
|
||||||
for (int j=0;j<sequence->clip_count();j++) {
|
for (int j=0;j<sequence->clip_count();j++) {
|
||||||
Clip* c = sequence->get_clip(j);
|
Clip* c = sequence->get_clip(j);
|
||||||
if (c != NULL && c->media == m) {
|
if (c != NULL && c->media == m) {
|
||||||
@@ -292,23 +302,47 @@ void Project::import_dialog() {
|
|||||||
process_file_list(files);
|
process_file_list(files);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Project::set_item_to_folder(QTreeWidgetItem* item) {
|
||||||
|
item->setData(0, Qt::UserRole + 1, MEDIA_TYPE_FOLDER);
|
||||||
|
}
|
||||||
|
|
||||||
Media* Project::get_media_from_tree(QTreeWidgetItem* item) {
|
Media* Project::get_media_from_tree(QTreeWidgetItem* item) {
|
||||||
return reinterpret_cast<Media*>(item->data(0, Qt::UserRole + 1).value<quintptr>());
|
return reinterpret_cast<Media*>(item->data(0, Qt::UserRole + 2).value<quintptr>());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Project::set_media_of_tree(QTreeWidgetItem* item, Media* media) {
|
void Project::set_media_of_tree(QTreeWidgetItem* item, Media* media) {
|
||||||
item->setData(0, Qt::UserRole + 1, QVariant::fromValue(reinterpret_cast<quintptr>(media)));
|
item->setData(0, Qt::UserRole + 1, MEDIA_TYPE_FOOTAGE);
|
||||||
|
item->setData(0, Qt::UserRole + 2, QVariant::fromValue(reinterpret_cast<quintptr>(media)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Sequence* Project::get_sequence_from_tree(QTreeWidgetItem* item) {
|
||||||
|
return reinterpret_cast<Sequence*>(item->data(0, Qt::UserRole + 2).value<quintptr>());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Project::set_sequence_of_tree(QTreeWidgetItem* item, Sequence* sequence) {
|
||||||
|
item->setData(0, Qt::UserRole + 1, MEDIA_TYPE_SEQUENCE);
|
||||||
|
item->setData(0, Qt::UserRole + 2, QVariant::fromValue(reinterpret_cast<quintptr>(sequence)));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Project::get_type_from_tree(QTreeWidgetItem* item) {
|
||||||
|
return item->data(0, Qt::UserRole + 1).toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Project::delete_media(QTreeWidgetItem* item) {
|
void Project::delete_media(QTreeWidgetItem* item) {
|
||||||
Media* m = get_media_from_tree(item);
|
int type = get_type_from_tree(item);
|
||||||
if (m->type == MEDIA_TYPE_SEQUENCE) {
|
switch (type) {
|
||||||
if (sequence == m->sequence) {
|
case MEDIA_TYPE_FOOTAGE:
|
||||||
|
delete get_media_from_tree(item);
|
||||||
|
break;
|
||||||
|
case MEDIA_TYPE_SEQUENCE:
|
||||||
|
Sequence* s = get_sequence_from_tree(item);
|
||||||
|
if (sequence == s) {
|
||||||
set_sequence(NULL);
|
set_sequence(NULL);
|
||||||
}
|
}
|
||||||
delete m->sequence;
|
delete s;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
delete m;
|
|
||||||
project_changed = true;
|
project_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,8 +607,9 @@ void Project::save_project() {
|
|||||||
int len = ui->treeWidget->topLevelItemCount();
|
int len = ui->treeWidget->topLevelItemCount();
|
||||||
stream.writeStartElement("media");
|
stream.writeStartElement("media");
|
||||||
for (int i=0;i<len;i++) {
|
for (int i=0;i<len;i++) {
|
||||||
Media* m = get_media_from_tree(ui->treeWidget->topLevelItem(i));
|
QTreeWidgetItem* item = ui->treeWidget->topLevelItem(i);
|
||||||
if (m->type == MEDIA_TYPE_FOOTAGE) {
|
if (get_type_from_tree(item) == MEDIA_TYPE_FOOTAGE) {
|
||||||
|
Media* m = get_media_from_tree(item);
|
||||||
m->save_id = i;
|
m->save_id = i;
|
||||||
stream.writeStartElement("footage");
|
stream.writeStartElement("footage");
|
||||||
stream.writeAttribute("id", QString::number(i));
|
stream.writeAttribute("id", QString::number(i));
|
||||||
@@ -587,9 +622,9 @@ void Project::save_project() {
|
|||||||
|
|
||||||
stream.writeStartElement("timeline");
|
stream.writeStartElement("timeline");
|
||||||
for (int i=0;i<len;i++) {
|
for (int i=0;i<len;i++) {
|
||||||
Media* m = get_media_from_tree(ui->treeWidget->topLevelItem(i));
|
QTreeWidgetItem* item = ui->treeWidget->topLevelItem(i);
|
||||||
if (m->type == MEDIA_TYPE_SEQUENCE) {
|
if (get_type_from_tree(item) == MEDIA_TYPE_SEQUENCE) {
|
||||||
Sequence* s = m->sequence;
|
Sequence* s = get_sequence_from_tree(item);
|
||||||
stream.writeStartElement("sequence");
|
stream.writeStartElement("sequence");
|
||||||
stream.writeTextElement("name", s->name);
|
stream.writeTextElement("name", s->name);
|
||||||
stream.writeTextElement("width", QString::number(s->width));
|
stream.writeTextElement("width", QString::number(s->width));
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ class Viewer;
|
|||||||
class SourceTable;
|
class SourceTable;
|
||||||
class QTreeWidgetItem;
|
class QTreeWidgetItem;
|
||||||
|
|
||||||
|
#define MEDIA_TYPE_FOOTAGE 0
|
||||||
|
#define MEDIA_TYPE_SEQUENCE 1
|
||||||
|
#define MEDIA_TYPE_FOLDER 2
|
||||||
|
#define MEDIA_TYPE_SOLID 3
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class Project;
|
class Project;
|
||||||
}
|
}
|
||||||
@@ -40,12 +45,19 @@ public:
|
|||||||
void load_project();
|
void load_project();
|
||||||
void save_project();
|
void save_project();
|
||||||
|
|
||||||
|
void new_folder();
|
||||||
|
|
||||||
|
int get_type_from_tree(QTreeWidgetItem* item);
|
||||||
Media* get_media_from_tree(QTreeWidgetItem* item);
|
Media* get_media_from_tree(QTreeWidgetItem* item);
|
||||||
void set_media_of_tree(QTreeWidgetItem* item, Media* media);
|
void set_media_of_tree(QTreeWidgetItem* item, Media* media);
|
||||||
|
Sequence* get_sequence_from_tree(QTreeWidgetItem* item);
|
||||||
|
void set_sequence_of_tree(QTreeWidgetItem* item, Sequence* sequence);
|
||||||
|
void set_item_to_folder(QTreeWidgetItem* item);
|
||||||
|
|
||||||
SourceTable* source_table;
|
SourceTable* source_table;
|
||||||
private:
|
private:
|
||||||
Ui::Project *ui;
|
Ui::Project *ui;
|
||||||
|
QTreeWidgetItem* new_item();
|
||||||
private slots:
|
private slots:
|
||||||
void rename_media(QTreeWidgetItem* item, int column);
|
void rename_media(QTreeWidgetItem* item, int column);
|
||||||
};
|
};
|
||||||
|
|||||||
+7
-1
@@ -35,6 +35,9 @@
|
|||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="SourceTable" name="treeWidget">
|
<widget class="SourceTable" name="treeWidget">
|
||||||
|
<property name="acceptDrops">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
<property name="editTriggers">
|
<property name="editTriggers">
|
||||||
<set>QAbstractItemView::NoEditTriggers</set>
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
</property>
|
</property>
|
||||||
@@ -51,7 +54,10 @@
|
|||||||
<enum>QAbstractItemView::SelectRows</enum>
|
<enum>QAbstractItemView::SelectRows</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="rootIsDecorated">
|
<property name="rootIsDecorated">
|
||||||
<bool>false</bool>
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="itemsExpandable">
|
||||||
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="sortingEnabled">
|
<property name="sortingEnabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
|||||||
+17
-1
@@ -10,6 +10,7 @@
|
|||||||
#include <QtMath>
|
#include <QtMath>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
|
#define AUDIO_MONITOR_PEAK_HEIGHT 15
|
||||||
#define AUDIO_MONITOR_GAP 3
|
#define AUDIO_MONITOR_GAP 3
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -39,24 +40,39 @@ void AudioMonitor::paintEvent(QPaintEvent *) {
|
|||||||
QPainter p(this);
|
QPainter p(this);
|
||||||
int channel_x = AUDIO_MONITOR_GAP;
|
int channel_x = AUDIO_MONITOR_GAP;
|
||||||
int channel_count = av_get_channel_layout_nb_channels(sequence->audio_layout);
|
int channel_count = av_get_channel_layout_nb_channels(sequence->audio_layout);
|
||||||
|
if (peaks.size() != channel_count) {
|
||||||
|
peaks.resize(channel_count);
|
||||||
|
peaks.fill(false);
|
||||||
|
}
|
||||||
int channel_width = (width()/channel_count) - AUDIO_MONITOR_GAP;
|
int channel_width = (width()/channel_count) - AUDIO_MONITOR_GAP;
|
||||||
long playhead_offset = -1;
|
long playhead_offset = -1;
|
||||||
int i;
|
int i;
|
||||||
for (i=0;i<channel_count;i++) {
|
for (i=0;i<channel_count;i++) {
|
||||||
QRect r(channel_x, 0, channel_width, height());
|
QRect r(channel_x, AUDIO_MONITOR_PEAK_HEIGHT + AUDIO_MONITOR_GAP, channel_width, height());
|
||||||
p.fillRect(r, gradient);
|
p.fillRect(r, gradient);
|
||||||
|
|
||||||
if (sample_cache_offset != -1) {
|
if (sample_cache_offset != -1) {
|
||||||
playhead_offset = (panel_timeline->playhead - sample_cache_offset) * channel_count;
|
playhead_offset = (panel_timeline->playhead - sample_cache_offset) * channel_count;
|
||||||
if (playhead_offset >= 0 && playhead_offset < sample_cache.size()) {
|
if (playhead_offset >= 0 && playhead_offset < sample_cache.size()) {
|
||||||
double multiplier = 1 - qAbs((double) sample_cache.at(playhead_offset+i) / 32768.0); // 16-bit int divided to float
|
double multiplier = 1 - qAbs((double) sample_cache.at(playhead_offset+i) / 32768.0); // 16-bit int divided to float
|
||||||
|
if (multiplier == (double) 0) {
|
||||||
|
peaks[i] = true;
|
||||||
|
}
|
||||||
r.setHeight(r.height()*multiplier);
|
r.setHeight(r.height()*multiplier);
|
||||||
} else {
|
} else {
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRect peak_rect(channel_x, 0, channel_width, AUDIO_MONITOR_PEAK_HEIGHT);
|
||||||
|
if (peaks.at(i)) {
|
||||||
|
p.fillRect(peak_rect, QColor(255, 0, 0));
|
||||||
|
} else {
|
||||||
|
p.fillRect(peak_rect, QColor(64, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
p.fillRect(r, QColor(0, 0, 0, 160));
|
p.fillRect(r, QColor(0, 0, 0, 160));
|
||||||
|
|
||||||
channel_x += channel_width + AUDIO_MONITOR_GAP;
|
channel_x += channel_width + AUDIO_MONITOR_GAP;
|
||||||
}
|
}
|
||||||
if (playhead_offset > -1) {
|
if (playhead_offset > -1) {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ public slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QLinearGradient gradient;
|
QLinearGradient gradient;
|
||||||
|
QVector<bool> peaks;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // AUDIOMONITOR_H
|
#endif // AUDIOMONITOR_H
|
||||||
|
|||||||
+31
-9
@@ -13,14 +13,9 @@
|
|||||||
|
|
||||||
SourceTable::SourceTable(QWidget* parent) : QTreeWidget(parent) {
|
SourceTable::SourceTable(QWidget* parent) : QTreeWidget(parent) {
|
||||||
sortByColumn(0, Qt::AscendingOrder);
|
sortByColumn(0, Qt::AscendingOrder);
|
||||||
setAcceptDrops(true);
|
|
||||||
editing_item = NULL;
|
|
||||||
rename_timer.setInterval(500);
|
rename_timer.setInterval(500);
|
||||||
connect(&rename_timer, SIGNAL(timeout()), this, SLOT(rename_interval()));
|
connect(&rename_timer, SIGNAL(timeout()), this, SLOT(rename_interval()));
|
||||||
connect(this, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(item_click(QTreeWidgetItem*,int)));
|
connect(this, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(item_click(QTreeWidgetItem*,int)));
|
||||||
// connect(this, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(stop_rename_timer()));
|
|
||||||
|
|
||||||
// connect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, )
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SourceTable::stop_rename_timer() {
|
void SourceTable::stop_rename_timer() {
|
||||||
@@ -50,9 +45,8 @@ void SourceTable::mouseDoubleClickEvent(QMouseEvent* ) {
|
|||||||
panel_project->import_dialog();
|
panel_project->import_dialog();
|
||||||
} else if (selectedItems().count() == 1) {
|
} else if (selectedItems().count() == 1) {
|
||||||
QTreeWidgetItem* item = selectedItems().at(0);
|
QTreeWidgetItem* item = selectedItems().at(0);
|
||||||
Media* m = reinterpret_cast<Media*>(item->data(0, Qt::UserRole + 1).value<quintptr>());
|
if (panel_project->get_type_from_tree(item) == MEDIA_TYPE_SEQUENCE) {
|
||||||
if (m->type == MEDIA_TYPE_SEQUENCE) {
|
set_sequence(panel_project->get_sequence_from_tree(item));
|
||||||
set_sequence(m->sequence);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,7 +69,6 @@ void SourceTable::dragMoveEvent(QDragMoveEvent *event) {
|
|||||||
|
|
||||||
void SourceTable::dropEvent(QDropEvent* event) {
|
void SourceTable::dropEvent(QDropEvent* event) {
|
||||||
const QMimeData* mimeData = event->mimeData();
|
const QMimeData* mimeData = event->mimeData();
|
||||||
|
|
||||||
if (mimeData->hasUrls()) {
|
if (mimeData->hasUrls()) {
|
||||||
QList<QUrl> urls = mimeData->urls();
|
QList<QUrl> urls = mimeData->urls();
|
||||||
if (!urls.isEmpty()) {
|
if (!urls.isEmpty()) {
|
||||||
@@ -87,5 +80,34 @@ void SourceTable::dropEvent(QDropEvent* event) {
|
|||||||
panel_project->process_file_list(paths);
|
panel_project->process_file_list(paths);
|
||||||
}
|
}
|
||||||
event->acceptProposedAction();
|
event->acceptProposedAction();
|
||||||
|
} else {
|
||||||
|
QTreeWidgetItem* item = itemAt(event->pos());
|
||||||
|
if (item == NULL || (item != NULL && panel_project->get_type_from_tree(item) == MEDIA_TYPE_FOLDER)) {
|
||||||
|
QList<QTreeWidgetItem*> items = selectedItems();
|
||||||
|
for (int i=0;i<items.size();i++) {
|
||||||
|
QTreeWidgetItem* s = items.at(i);
|
||||||
|
bool ignore = false;
|
||||||
|
if (s->parent() == NULL) {
|
||||||
|
takeTopLevelItem(indexOfTopLevelItem(s));
|
||||||
|
} else {
|
||||||
|
// if child belongs to a selected parent, assume the user is just moving the parent and ignore the child
|
||||||
|
for (int j=0;j<items.size();j++) {
|
||||||
|
if (s->parent() == items.at(j)) {
|
||||||
|
ignore = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ignore) s->parent()->takeChild(s->parent()->indexOfChild(s));
|
||||||
|
}
|
||||||
|
if (!ignore) {
|
||||||
|
if (item == NULL) {
|
||||||
|
addTopLevelItem(s);
|
||||||
|
} else {
|
||||||
|
item->addChild(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
project_changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-21
@@ -59,27 +59,29 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
|
|||||||
panel_timeline->drag_frame_start = entry_point + panel_timeline->getFrameFromScreenPoint(50);
|
panel_timeline->drag_frame_start = entry_point + panel_timeline->getFrameFromScreenPoint(50);
|
||||||
panel_timeline->drag_track_start = (bottom_align) ? -1 : 0;
|
panel_timeline->drag_track_start = (bottom_align) ? -1 : 0;
|
||||||
for (int i=0;i<items.size();i++) {
|
for (int i=0;i<items.size();i++) {
|
||||||
bool ignore_infinite_length = false;
|
QTreeWidgetItem* item = items.at(i);
|
||||||
Media* m = panel_project->get_media_from_tree(items.at(i));
|
if (panel_project->get_type_from_tree(item) == MEDIA_TYPE_FOOTAGE) {
|
||||||
Ghost g;
|
Media* m = panel_project->get_media_from_tree(item);
|
||||||
g.clip = -1;
|
bool ignore_infinite_length = (m->audio_tracks.size() > 0);
|
||||||
g.media = m;
|
Ghost g;
|
||||||
g.old_clip_in = g.clip_in = 0;
|
g.clip = -1;
|
||||||
g.in = entry_point;
|
g.media = m;
|
||||||
entry_point += m->get_length_in_frames(sequence->frame_rate);
|
g.old_clip_in = g.clip_in = 0;
|
||||||
g.out = entry_point;
|
g.in = entry_point;
|
||||||
g.trimming = false;
|
entry_point += m->get_length_in_frames(sequence->frame_rate);
|
||||||
for (int j=0;j<m->audio_tracks.size();j++) {
|
g.out = entry_point;
|
||||||
g.track = j;
|
g.trimming = false;
|
||||||
g.media_stream = m->audio_tracks.at(j);
|
for (int j=0;j<m->audio_tracks.size();j++) {
|
||||||
ignore_infinite_length = true;
|
g.track = j;
|
||||||
panel_timeline->ghosts.append(g);
|
g.media_stream = m->audio_tracks.at(j);
|
||||||
}
|
panel_timeline->ghosts.append(g);
|
||||||
for (int j=0;j<m->video_tracks.size();j++) {
|
}
|
||||||
g.track = -1-j;
|
for (int j=0;j<m->video_tracks.size();j++) {
|
||||||
g.media_stream = m->video_tracks.at(j);
|
g.track = -1-j;
|
||||||
if (m->video_tracks[j]->infinite_length && !ignore_infinite_length) g.out = g.in + 100;
|
g.media_stream = m->video_tracks.at(j);
|
||||||
panel_timeline->ghosts.append(g);
|
if (m->video_tracks[j]->infinite_length && !ignore_infinite_length) g.out = g.in + 100;
|
||||||
|
panel_timeline->ghosts.append(g);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||||
|
|||||||
Reference in New Issue
Block a user