wave effect axis, fixed folder bugs, timecode to frame number, drag from footage viewer, track resizing bug

This commit is contained in:
itsmattkc
2018-10-20 13:57:37 +11:00
parent ca3f5aa0ba
commit c9b8775a81
13 changed files with 324 additions and 147 deletions
+26 -14
View File
@@ -136,21 +136,33 @@ void LabelSlider::mouseReleaseEvent(QMouseEvent*) {
drag_proc = false;
previous_value = drag_start_value;
emit valueChanged();
} else {
double d = QInputDialog::getDouble(
this,
"Set Value",
"New value:",
(display_type == LABELSLIDER_PERCENT) ? internal_value * 100 : internal_value,
(min_enabled) ? min_value : INT_MIN,
(max_enabled) ? max_value : INT_MAX,
decimal_places
);
if (display_type == LABELSLIDER_PERCENT) d *= 0.01;
if (d != internal_value) {
} else {
double d = internal_value;
if (display_type == LABELSLIDER_FRAMENUMBER) {
QString s = QInputDialog::getText(
this,
"Set Value",
"New value:",
QLineEdit::Normal,
valueToString(internal_value)
);
d = timecode_to_frame(s, config.timecode_view, frame_rate); // string to frame number
} else {
d = QInputDialog::getDouble(
this,
"Set Value",
"New value:",
(display_type == LABELSLIDER_PERCENT) ? internal_value * 100 : internal_value,
(min_enabled) ? min_value : INT_MIN,
(max_enabled) ? max_value : INT_MAX,
decimal_places
);
if (display_type == LABELSLIDER_PERCENT) d *= 0.01;
}
if (d != internal_value) {
previous_value = internal_value;
set_value(d, true);
}
}
}
}
}
}
+24 -20
View File
@@ -112,7 +112,7 @@ void SourceTable::rename_interval() {
}
}
void SourceTable::item_click(QTreeWidgetItem* item, int column) {
if (column == 0) {
if (column == 0 && selectedItems().size() == 1) {
editing_item = item;
rename_timer.start();
}
@@ -186,30 +186,34 @@ void SourceTable::dropEvent(QDropEvent* event) {
}
event->acceptProposedAction();
} else {
event->ignore();
// dragging files within project
QVector<QTreeWidgetItem*> move_items;
// if we dragged to the root OR dragged to a folder
if (drop_item == NULL || (drop_item != NULL && get_type_from_tree(drop_item) == MEDIA_TYPE_FOLDER)) {
QVector<QTreeWidgetItem*> move_items;
QList<QTreeWidgetItem*> selected_items = selectedItems();
for (int i=0;i<selected_items.size();i++) {
QTreeWidgetItem* s = selected_items.at(i);
bool ignore = false;
if (s->parent() != NULL) {
// if child belongs to a selected parent, assume the user is just moving the parent and ignore the child
QTreeWidgetItem* par = s->parent();
while (par != NULL) {
for (int j=0;j<selected_items.size();j++) {
if (par == selected_items.at(j)) {
ignore = true;
break;
}
}
par = par->parent();
}
}
if (!ignore) {
move_items.append(s);
}
if (s->parent() != drop_item && s != drop_item) {
bool ignore = false;
if (s->parent() != NULL) {
// if child belongs to a selected parent, assume the user is just moving the parent and ignore the child
QTreeWidgetItem* par = s->parent();
while (par != NULL && !ignore) {
for (int j=0;j<selected_items.size();j++) {
if (par == selected_items.at(j)) {
ignore = true;
break;
}
}
par = par->parent();
}
}
if (!ignore) {
move_items.append(s);
}
}
}
if (move_items.size() > 0) {
MediaMove* mm = new MediaMove(this);
@@ -217,6 +221,6 @@ void SourceTable::dropEvent(QDropEvent* event) {
mm->items = move_items;
undo_stack.push(mm);
}
}
}
}
}
+144 -98
View File
@@ -13,6 +13,7 @@
#include "project/undo.h"
#include "ui_timeline.h"
#include "mainwindow.h"
#include "ui/viewerwidget.h"
#include "effects/effect.h"
#include "effects/transition.h"
@@ -191,13 +192,59 @@ bool same_sign(int a, int b) {
}
void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
if (event->source() == panel_project->source_table) {
qDebug() << "DRAG ENTER CALLED";
bool import_init = false;
QVector<void*> media_list;
QVector<int> type_list;
if (event->source() == panel_project->source_table) {
QList<QTreeWidgetItem*> items = panel_project->source_table->selectedItems();
media_list.resize(items.size());
type_list.resize(items.size());
for (int i=0;i<items.size();i++) {
type_list[i] = get_type_from_tree(items.at(i));
media_list[i] = get_media_from_tree(items.at(i));
}
import_init = true;
}
if (event->source() == panel_footage_viewer->viewer_widget) {
Sequence* proposed_seq = panel_footage_viewer->seq;
if (proposed_seq != sequence) { // don't allow nesting the same sequence
if (proposed_seq->wrapper_sequence) {
type_list.append(MEDIA_TYPE_FOOTAGE);
media_list.append(proposed_seq->clips.at(0)->media);
} else {
type_list.append(MEDIA_TYPE_SEQUENCE);
media_list.append(proposed_seq);
}
import_init = true;
}
}
/*if (config.enable_drag_files_to_timeline && event->mimeData()->hasUrls()) {
// TODO for this to work, we need a way to abort PreviewGenerator
qDebug() << "TODO get data for:";
QList<QUrl> urls = event->mimeData()->urls();
if (!urls.isEmpty()) {
for (int i=0;i<urls.size();i++) {
qDebug() << (urls.at(i).toLocalFile());
}
}
import_init = true;
}*/
if (import_init) {
event->accept();
panel_timeline->video_ghosts = false;
panel_timeline->audio_ghosts = false;
QPoint pos = event->pos();
QList<QTreeWidgetItem*> items = panel_project->source_table->selectedItems();
QPoint pos = event->pos();
long entry_point;
if (sequence == NULL) {
// if no sequence, we're going to create a new one using the clips as a reference
@@ -212,12 +259,11 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
bool got_video_values = false;
bool got_audio_values = false;
for (int i=0;i<items.size();i++) {
QTreeWidgetItem* item = items.at(i);
switch (get_type_from_tree(item)) {
for (int i=0;i<media_list.size();i++) {
switch (type_list.at(i)) {
case MEDIA_TYPE_FOOTAGE:
{
Media* m = get_footage_from_tree(item);
Media* m = static_cast<Media*>(media_list.at(i));
if (m->ready) {
if (!got_video_values) {
for (int j=0;j<m->video_tracks.size();j++) {
@@ -246,7 +292,7 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
break;
case MEDIA_TYPE_SEQUENCE:
{
Sequence* s = get_sequence_from_tree(item);
Sequence* s = static_cast<Sequence*>(media_list.at(i));
predicted_video_width = s->width;
predicted_video_height = s->height;
predicted_new_frame_rate = s->frame_rate;
@@ -266,9 +312,7 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
panel_timeline->drag_track_start = (bottom_align) ? -1 : 0;
predicted_new_frame_rate = sequence->frame_rate;
}
for (int i=0;i<items.size();i++) {
QTreeWidgetItem* item = items.at(i);
int item_type = get_type_from_tree(item);
for (int i=0;i<media_list.size();i++) {
bool can_import = true;
Media* m = NULL;
@@ -278,9 +322,9 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
long default_clip_in = 0;
long default_clip_out = 0;
switch (item_type) {
switch (type_list.at(i)) {
case MEDIA_TYPE_FOOTAGE:
m = get_footage_from_tree(item);
m = static_cast<Media*>(media_list.at(i));
media = m;
can_import = m->ready;
if (m->using_inout) {
@@ -291,7 +335,7 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
}
break;
case MEDIA_TYPE_SEQUENCE:
s = get_sequence_from_tree(item);
s = static_cast<Sequence*>(media_list.at(i));
sequence_length = s->getEndFrame();
if (sequence != NULL) sequence_length = refactor_frame_number(sequence_length, s->frame_rate, predicted_new_frame_rate);
media = s;
@@ -308,14 +352,14 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
if (can_import) {
Ghost g;
g.clip = -1;
g.media_type = item_type;
g.media_type = type_list.at(i);
g.trimming = false;
g.old_clip_in = g.clip_in = default_clip_in;
g.media = media;
g.in = entry_point;
g.transition = NULL;
switch (item_type) {
switch (type_list.at(i)) {
case MEDIA_TYPE_FOOTAGE:
// is video source a still image?
if (m->video_tracks.size() > 0 && m->video_tracks[0]->infinite_length && m->audio_tracks.size() == 0) {
@@ -367,18 +411,7 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
g.old_track = g.track;
}
panel_timeline->importing = true;
} else if (config.enable_drag_files_to_timeline && event->mimeData()->hasUrls()) {
// TODO for this to work, we need a way to abort PreviewGenerator
/*event->accept();
qDebug() << "TODO get data for:";
QList<QUrl> urls = event->mimeData()->urls();
if (!urls.isEmpty()) {
for (int i=0;i<urls.size();i++) {
qDebug() << (urls.at(i).toLocalFile());
}
}*/
}
}
}
void TimelineWidget::dragMoveEvent(QDragMoveEvent *event) {
@@ -1284,7 +1317,12 @@ void TimelineWidget::update_ghosts(QPoint& mouse_pos) {
if (panel_timeline->importing) {
QToolTip::showText(mapToGlobal(mouse_pos), frame_to_timecode(earliest_in_point, config.timecode_view, sequence->frame_rate));
} else {
QToolTip::showText(mapToGlobal(mouse_pos), ((frame_diff < 0) ? "-" : "+") + frame_to_timecode(qAbs(frame_diff), config.timecode_view, sequence->frame_rate));
QToolTip::showText(mapToGlobal(mouse_pos),
((frame_diff < 0) ? "-" : "+")
+ frame_to_timecode(qAbs(frame_diff), config.timecode_view, sequence->frame_rate)
+ " Duration: "
+ frame_to_timecode((panel_timeline->ghosts.at(0).old_out-panel_timeline->ghosts.at(0).old_in)+frame_diff, config.timecode_view, sequence->frame_rate)
);
}
}
@@ -1666,71 +1704,77 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
bool found = false;
bool cursor_contains_clip = false;
int closeness = INT_MAX;
int min_track = INT_MAX;
int max_track = INT_MIN;
panel_timeline->transition_select = TA_NO_TRANSITION;
for (int i=0;i<sequence->clips.size();i++) {
Clip* c = sequence->clips.at(i);
if (c != NULL && c->track == mouse_track) {
if (panel_timeline->cursor_frame >= c->timeline_in &&
panel_timeline->cursor_frame <= c->timeline_out) {
cursor_contains_clip = true;
if (c != NULL) {
min_track = qMin(min_track, c->track);
max_track = qMax(max_track, c->track);
if (c->track == mouse_track) {
if (panel_timeline->cursor_frame >= c->timeline_in &&
panel_timeline->cursor_frame <= c->timeline_out) {
cursor_contains_clip = true;
tooltip_timer.start();
tooltip_clip = i;
tooltip_timer.start();
tooltip_clip = i;
if (c->opening_transition != NULL && panel_timeline->cursor_frame <= c->timeline_in + c->opening_transition->length) {
panel_timeline->transition_select = TA_OPENING_TRANSITION;
} else if (c->closing_transition != NULL && panel_timeline->cursor_frame >= c->timeline_out - c->closing_transition->length) {
panel_timeline->transition_select = TA_CLOSING_TRANSITION;
}
}
if (c->timeline_in > mouse_frame_lower && c->timeline_in < mouse_frame_upper) {
int nc = qAbs(c->timeline_in + 1 - panel_timeline->cursor_frame);
if (nc < closeness) {
panel_timeline->trim_target = i;
panel_timeline->trim_in_point = true;
closeness = nc;
found = true;
}
}
if (c->timeline_out > mouse_frame_lower && c->timeline_out < mouse_frame_upper) {
int nc = qAbs(c->timeline_out - 1 - panel_timeline->cursor_frame);
if (nc < closeness) {
panel_timeline->trim_target = i;
panel_timeline->trim_in_point = false;
closeness = nc;
found = true;
}
}
if (panel_timeline->tool == TIMELINE_TOOL_POINTER) {
if (c->opening_transition != NULL) {
long transition_point = c->timeline_in + c->opening_transition->length;
if (transition_point > mouse_frame_lower && transition_point < mouse_frame_upper) {
int nc = qAbs(transition_point - 1 - panel_timeline->cursor_frame);
if (nc < closeness) {
panel_timeline->trim_target = i;
panel_timeline->trim_in_point = false;
panel_timeline->transition_select = TA_OPENING_TRANSITION;
closeness = nc;
found = true;
}
if (c->opening_transition != NULL && panel_timeline->cursor_frame <= c->timeline_in + c->opening_transition->length) {
panel_timeline->transition_select = TA_OPENING_TRANSITION;
} else if (c->closing_transition != NULL && panel_timeline->cursor_frame >= c->timeline_out - c->closing_transition->length) {
panel_timeline->transition_select = TA_CLOSING_TRANSITION;
}
}
if (c->closing_transition != NULL) {
long transition_point = c->timeline_out - c->closing_transition->length;
if (transition_point > mouse_frame_lower && transition_point < mouse_frame_upper) {
int nc = qAbs(transition_point + 1 - panel_timeline->cursor_frame);
if (nc < closeness) {
panel_timeline->trim_target = i;
panel_timeline->trim_in_point = true;
panel_timeline->transition_select = TA_CLOSING_TRANSITION;
closeness = nc;
found = true;
if (c->timeline_in > mouse_frame_lower && c->timeline_in < mouse_frame_upper) {
int nc = qAbs(c->timeline_in + 1 - panel_timeline->cursor_frame);
if (nc < closeness) {
panel_timeline->trim_target = i;
panel_timeline->trim_in_point = true;
closeness = nc;
found = true;
}
}
if (c->timeline_out > mouse_frame_lower && c->timeline_out < mouse_frame_upper) {
int nc = qAbs(c->timeline_out - 1 - panel_timeline->cursor_frame);
if (nc < closeness) {
panel_timeline->trim_target = i;
panel_timeline->trim_in_point = false;
closeness = nc;
found = true;
}
}
if (panel_timeline->tool == TIMELINE_TOOL_POINTER) {
if (c->opening_transition != NULL) {
long transition_point = c->timeline_in + c->opening_transition->length;
if (transition_point > mouse_frame_lower && transition_point < mouse_frame_upper) {
int nc = qAbs(transition_point - 1 - panel_timeline->cursor_frame);
if (nc < closeness) {
panel_timeline->trim_target = i;
panel_timeline->trim_in_point = false;
panel_timeline->transition_select = TA_OPENING_TRANSITION;
closeness = nc;
found = true;
}
}
}
if (c->closing_transition != NULL) {
long transition_point = c->timeline_out - c->closing_transition->length;
if (transition_point > mouse_frame_lower && transition_point < mouse_frame_upper) {
int nc = qAbs(transition_point + 1 - panel_timeline->cursor_frame);
if (nc < closeness) {
panel_timeline->trim_target = i;
panel_timeline->trim_in_point = true;
panel_timeline->transition_select = TA_CLOSING_TRANSITION;
closeness = nc;
found = true;
}
}
}
}
}
}
}
}
/*if (cursor_contains_clip) {
QToolTip::showText(mapToGlobal(event->pos()), "HOVER OVER CLIP");
@@ -1744,21 +1788,23 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
int track_y = 0;
for (int i=0;i<panel_timeline->get_track_height_size(bottom_align);i++) {
int track = (bottom_align) ? -1-i : i;
int track_height = panel_timeline->calculate_track_height(track, -1);
track_y += track_height;
int y_test_value = (bottom_align) ? rect().bottom() - track_y : track_y;
int test_range = 5;
int mouse_pos = pos.y() + scroll;
if (mouse_pos > y_test_value-test_range && mouse_pos < y_test_value+test_range) {
// if track lines are hidden, only resize track if a clip is already there
if (config.show_track_lines || cursor_contains_clip) {
found = true;
track_resizing = true;
track_target = track;
track_resize_old_value = track_height;
}
break;
}
if (track >= min_track && track <= max_track) {
int track_height = panel_timeline->calculate_track_height(track, -1);
track_y += track_height;
int y_test_value = (bottom_align) ? rect().bottom() - track_y : track_y;
int test_range = 5;
int mouse_pos = pos.y() + scroll;
if (mouse_pos > y_test_value-test_range && mouse_pos < y_test_value+test_range) {
// if track lines are hidden, only resize track if a clip is already there
if (config.show_track_lines || cursor_contains_clip) {
found = true;
track_resizing = true;
track_target = track;
track_resize_old_value = track_height;
}
break;
}
}
}
if (found) {
+42 -5
View File
@@ -21,6 +21,9 @@
#include <QtMath>
#include <QOpenGLFramebufferObject>
#include <QOpenGLFunctions>
#include <QMouseEvent>
#include <QMimeData>
#include <QDrag>
extern "C" {
#include <libavformat/avformat.h>
@@ -29,7 +32,8 @@ extern "C" {
ViewerWidget::ViewerWidget(QWidget *parent) :
QOpenGLWidget(parent),
default_fbo(NULL),
waveform(false)
waveform(false),
dragging(false)
{
setFocusPolicy(Qt::ClickFocus);
@@ -67,7 +71,34 @@ void ViewerWidget::paintEvent(QPaintEvent *e) {
if (!rendering) {
makeCurrent();
QOpenGLWidget::paintEvent(e);
}
}
}
void ViewerWidget::seek_from_click(int x) {
viewer->seek(getFrameFromScreenPoint((double) width() / (double) waveform_clip->timeline_out, x));
}
void ViewerWidget::mousePressEvent(QMouseEvent* event) {
if (waveform) seek_from_click(event->x());
dragging = true;
}
void ViewerWidget::mouseMoveEvent(QMouseEvent* event) {
if (dragging) {
if (waveform) {
seek_from_click(event->x());
} else {
QDrag* drag = new QDrag(this);
QMimeData* mimeData = new QMimeData;
mimeData->setText("h");
drag->setMimeData(mimeData);
Qt::DropAction dropAction = drag->exec();
}
}
}
void ViewerWidget::mouseReleaseEvent(QMouseEvent *) {
dragging = false;
}
void ViewerWidget::drawTitleSafeArea() {
@@ -238,7 +269,7 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) {
}
}
if (viewer->playing && s->playhead == endFrame) {
if (viewer->playing && (s->playhead == endFrame || (s->using_workarea && s->playhead == s->workarea_out))) {
viewer->pause();
}
@@ -470,10 +501,16 @@ void ViewerWidget::paintGL() {
double timeline_zoom = (double) width() / (double) waveform_clip->timeline_out;
QPainter p(this);
p.setPen(QColor(0, 255, 0));
if (viewer->seq->using_workarea) {
p.fillRect(QRect(getScreenPointFromFrame(timeline_zoom, viewer->seq->workarea_in), 0, getScreenPointFromFrame(timeline_zoom, viewer->seq->workarea_out-viewer->seq->workarea_in), height()), QColor(255, 255, 255, 64));
int in_x = getScreenPointFromFrame(timeline_zoom, viewer->seq->workarea_in);
int out_x = getScreenPointFromFrame(timeline_zoom, viewer->seq->workarea_out);
p.fillRect(QRect(in_x, 0, out_x - in_x, height()), QColor(255, 255, 255, 64));
p.setPen(Qt::white);
p.drawLine(in_x, 0, in_x, height());
p.drawLine(out_x, 0, out_x, height());
}
p.setPen(Qt::green);
draw_waveform(waveform_clip, waveform_ms, waveform_clip->timeline_out, &p, rect(), 0, width(), waveform_zoom);
p.setPen(Qt::red);
int playhead_x = getScreenPointFromFrame(timeline_zoom, viewer->seq->playhead);
+7 -2
View File
@@ -32,14 +32,19 @@ public:
protected:
void paintEvent(QPaintEvent *e);
// void resizeGL(int w, int h);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
private:
QTimer retry_timer;
void drawTitleSafeArea();
bool dragging;
void seek_from_click(int x);
GLuint compose_sequence(Clip *nest, bool render_audio);
GLuint draw_clip(QOpenGLFramebufferObject *clip, GLuint texture);
private slots:
void retry();
void deleteFunction();
GLuint compose_sequence(Clip *nest, bool render_audio);
GLuint draw_clip(QOpenGLFramebufferObject *clip, GLuint texture);
};
#endif // VIEWERWIDGET_H