From 48b1c21d6c9ffd1e0857ec6c2e88fa82aa2a6ff0 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 19 Jul 2018 11:39:37 +0100 Subject: [PATCH] added #105 --- io/media.h | 3 + io/previewgenerator.cpp | 3 + mainwindow.cpp | 2 +- mainwindow.ui | 2 +- panels/timeline.cpp | 4 +- project/sequence.h | 2 +- ui/timelinewidget.cpp | 1307 +++++++++++++++++++++------------------ ui/timelinewidget.h | 6 + 8 files changed, 708 insertions(+), 621 deletions(-) diff --git a/io/media.h b/io/media.h index 1e7de7cc3..dd9a585be 100644 --- a/io/media.h +++ b/io/media.h @@ -15,7 +15,10 @@ struct MediaStream { int video_width; int video_height; bool infinite_length; + double video_frame_rate; int audio_channels; + int audio_layout; + int audio_frequency; // preview thumbnail/waveform bool preview_done; diff --git a/io/previewgenerator.cpp b/io/previewgenerator.cpp index 2804adced..7cd068b5a 100644 --- a/io/previewgenerator.cpp +++ b/io/previewgenerator.cpp @@ -35,10 +35,13 @@ void PreviewGenerator::parse_media() { bool infinite_length = (fmt_ctx->streams[i]->avg_frame_rate.den == 0); ms->video_width = fmt_ctx->streams[i]->codecpar->width; ms->video_height = fmt_ctx->streams[i]->codecpar->height; + ms->video_frame_rate = (infinite_length) ? 0 : av_q2d(fmt_ctx->streams[i]->avg_frame_rate); ms->infinite_length = infinite_length; media->video_tracks.append(ms); } else if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { ms->audio_channels = fmt_ctx->streams[i]->codecpar->channels; + ms->audio_layout = fmt_ctx->streams[i]->codecpar->channel_layout; + ms->audio_frequency = fmt_ctx->streams[i]->codecpar->sample_rate; media->audio_tracks.append(ms); } } diff --git a/mainwindow.cpp b/mainwindow.cpp index f352db73d..0957eaacb 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -110,7 +110,7 @@ MainWindow::MainWindow(QWidget *parent) : panel_project->load_project(); } } - autorecovery_timer.setInterval(10000); + autorecovery_timer.setInterval(60000); QObject::connect(&autorecovery_timer, SIGNAL(timeout()), this, SLOT(autorecover_interval())); autorecovery_timer.start(); diff --git a/mainwindow.ui b/mainwindow.ui index 0d74dc1fa..8f49bb0ca 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -215,7 +215,7 @@ &Redo - Ctrl+Y + Ctrl+Shift+Z, Ctrl+Y diff --git a/panels/timeline.cpp b/panels/timeline.cpp index 391dd4ed1..28a7245b5 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -214,8 +214,8 @@ void Timeline::update_sequence() { ui->pushButton_4->setEnabled(!null_sequence); ui->pushButton_5->setEnabled(!null_sequence); ui->headers->setEnabled(!null_sequence); - ui->video_area->setEnabled(!null_sequence); - ui->audio_area->setEnabled(!null_sequence); +// ui->video_area->setEnabled(!null_sequence); +// ui->audio_area->setEnabled(!null_sequence); if (null_sequence) { setWindowTitle("Timeline: "); diff --git a/project/sequence.h b/project/sequence.h index a74fce107..408b68e10 100644 --- a/project/sequence.h +++ b/project/sequence.h @@ -20,7 +20,7 @@ public: long getEndFrame(); int width; int height; - float frame_rate; + double frame_rate; int audio_frequency; int audio_layout; private: diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index fec5a125e..b1503d98b 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -55,12 +55,61 @@ void TimelineWidget::resizeEvent(QResizeEvent*) { void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { if (event->source() == panel_project->source_table) { event->accept(); - QPoint pos = event->pos(); - QList items = panel_project->source_table->selectedItems(); - long entry_point = panel_timeline->getFrameFromScreenPoint(pos.x()); - panel_timeline->drag_frame_start = entry_point + panel_timeline->getFrameFromScreenPoint(50); - panel_timeline->drag_track_start = (bottom_align) ? -1 : 0; - for (int i=0;ipos(); + QList items = panel_project->source_table->selectedItems(); + long entry_point; + if (sequence == NULL) { + // if no sequence, we're going to create a new one using the clips as a reference + entry_point = 0; + + // shitty hardcoded default values + predicted_video_width = 1920; + predicted_video_height = 1080; + predicted_new_frame_rate = 29.97; + predicted_audio_freq = 48000; + predicted_audio_layout = 3; + + bool got_video_values = false; + bool got_audio_values = false; + for (int i=0;iget_type_from_tree(item) == MEDIA_TYPE_FOOTAGE) { + Media* m = panel_project->get_media_from_tree(item); + if (m->ready) { + if (!got_video_values) { + for (int j=0;jvideo_tracks.size();j++) { + MediaStream* ms = m->video_tracks.at(j); + predicted_video_width = ms->video_width; + predicted_video_height = ms->video_height; + if (ms->video_frame_rate != 0) { + predicted_new_frame_rate = ms->video_frame_rate; + + // only break with a decent frame rate, otherwise there may be a better candidate + got_video_values = true; + break; + } + } + } + if (!got_audio_values) { + for (int j=0;jaudio_tracks.size();j++) { + MediaStream* ms = m->audio_tracks.at(j); + predicted_audio_freq = ms->audio_frequency; + got_audio_values = true; + break; + } + } + if (got_video_values && got_audio_values) break; + } + } + } + } else { + entry_point = panel_timeline->getFrameFromScreenPoint(pos.x()); + panel_timeline->drag_frame_start = entry_point + panel_timeline->getFrameFromScreenPoint(50); + panel_timeline->drag_track_start = (bottom_align) ? -1 : 0; + predicted_new_frame_rate = sequence->frame_rate; + } + for (int i=0;iget_type_from_tree(item) == MEDIA_TYPE_FOOTAGE) { Media* m = panel_project->get_media_from_tree(item); @@ -73,7 +122,7 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { if (m->video_tracks.size() > 0 && m->video_tracks[0]->infinite_length && m->audio_tracks.size() == 0) { g.out = g.in + 100; } else { - g.out = entry_point + m->get_length_in_frames(sequence->frame_rate); + g.out = entry_point + m->get_length_in_frames(predicted_new_frame_rate); } entry_point = g.out; g.trimming = false; @@ -96,14 +145,12 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { g.old_out = g.out; g.old_track = g.track; } - -// init_ghosts(); - panel_timeline->importing = true; + panel_timeline->importing = true; } } void TimelineWidget::dragMoveEvent(QDragMoveEvent *event) { - if (panel_timeline->importing) { + if (sequence != NULL && panel_timeline->importing) { QPoint pos = event->pos(); update_ghosts(pos); panel_timeline->repaint_timeline(); @@ -111,7 +158,7 @@ void TimelineWidget::dragMoveEvent(QDragMoveEvent *event) { } void TimelineWidget::dragLeaveEvent(QDragLeaveEvent*) { - if (panel_timeline->importing) { + if (sequence != NULL && panel_timeline->importing) { panel_timeline->ghosts.clear(); panel_timeline->importing = false; panel_timeline->repaint_timeline(); @@ -119,24 +166,38 @@ void TimelineWidget::dragLeaveEvent(QDragLeaveEvent*) { } void TimelineWidget::dropEvent(QDropEvent* event) { - if (panel_timeline->importing) { - event->accept(); + if (panel_timeline->importing && panel_timeline->ghosts.size() > 0) { + event->accept(); TimelineAction* ta = new TimelineAction(); QVector added_clips; - // delete areas before adding - QVector delete_areas; - for (int i=0;ighosts.size();i++) { - const Ghost& g = panel_timeline->ghosts.at(i); - Selection s; - s.in = g.in; - s.out = g.out; - s.track = g.track; - delete_areas.append(s); + if (sequence == NULL) { + Sequence* s = new Sequence(); + + // dumb hardcoded default values, should be settable somewhere + s->name = panel_project->get_next_sequence_name(); + s->width = predicted_video_width; + s->height = predicted_video_height; + s->frame_rate = predicted_new_frame_rate; + s->audio_frequency = predicted_audio_freq; + s->audio_layout = predicted_audio_layout; + + panel_project->new_sequence(s, true, NULL); + } else { + // delete areas before adding + QVector delete_areas; + for (int i=0;ighosts.size();i++) { + const Ghost& g = panel_timeline->ghosts.at(i); + Selection s; + s.in = g.in; + s.out = g.out; + s.track = g.track; + delete_areas.append(s); + } + panel_timeline->delete_areas_and_relink(ta, delete_areas); } - panel_timeline->delete_areas_and_relink(ta, delete_areas); // add clips for (int i=0;ighosts.size();i++) { @@ -222,303 +283,307 @@ void TimelineWidget::mouseDoubleClickEvent(QMouseEvent *event) { } void TimelineWidget::mousePressEvent(QMouseEvent *event) { - if (event->button() == Qt::LeftButton) { - if (panel_timeline->tool == TIMELINE_TOOL_EDIT || panel_timeline->tool == TIMELINE_TOOL_RAZOR) { - panel_timeline->drag_frame_start = panel_timeline->cursor_frame; - panel_timeline->drag_track_start = panel_timeline->cursor_track; - } else { - QPoint pos = event->pos(); - panel_timeline->drag_frame_start = panel_timeline->getFrameFromScreenPoint(pos.x()); - panel_timeline->drag_track_start = getTrackFromScreenPoint(pos.y()); - } - - int clip_index = panel_timeline->trim_target; - if (clip_index == -1) clip_index = getClipIndexFromCoords(panel_timeline->drag_frame_start, panel_timeline->drag_track_start); - - bool shift = (event->modifiers() & Qt::ShiftModifier); - - if (shift) { - panel_timeline->selection_offset = panel_timeline->selections.size(); - } else { - panel_timeline->selection_offset = 0; - } - - switch (panel_timeline->tool) { - case TIMELINE_TOOL_POINTER: - case TIMELINE_TOOL_RIPPLE: - case TIMELINE_TOOL_SLIP: - case TIMELINE_TOOL_ROLLING: - case TIMELINE_TOOL_SLIDE: - { - if (track_resizing) { - track_resize_mouse_cache = event->pos().y(); - panel_timeline->moving_init = true; + if (sequence != NULL) { + if (event->button() == Qt::LeftButton) { + if (panel_timeline->tool == TIMELINE_TOOL_EDIT || panel_timeline->tool == TIMELINE_TOOL_RAZOR) { + panel_timeline->drag_frame_start = panel_timeline->cursor_frame; + panel_timeline->drag_track_start = panel_timeline->cursor_track; } else { - if (clip_index >= 0) { - Clip* clip = sequence->get_clip(clip_index); - if (clip != NULL) { - if (panel_timeline->is_clip_selected(clip, true)) { - if (shift) { - // TODO if shift is down, deselect it - } - } else { - // if "shift" is not down - if (!shift) { - panel_timeline->selections.clear(); - } + QPoint pos = event->pos(); + panel_timeline->drag_frame_start = panel_timeline->getFrameFromScreenPoint(pos.x()); + panel_timeline->drag_track_start = getTrackFromScreenPoint(pos.y()); + } - Selection s; + int clip_index = panel_timeline->trim_target; + if (clip_index == -1) clip_index = getClipIndexFromCoords(panel_timeline->drag_frame_start, panel_timeline->drag_track_start); - s.in = clip->timeline_in; - s.out = clip->timeline_out; - s.track = clip->track; - panel_timeline->selections.append(s); + bool shift = (event->modifiers() & Qt::ShiftModifier); - if (panel_timeline->select_also_seeks) { - panel_timeline->seek(clip->timeline_in); - } + if (shift) { + panel_timeline->selection_offset = panel_timeline->selections.size(); + } else { + panel_timeline->selection_offset = 0; + } - // if alt is not down, select links - if (!(event->modifiers() & Qt::AltModifier)) { - for (int i=0;ilinked.size();i++) { - Clip* link = sequence->get_clip(clip->linked.at(i)); - if (!panel_timeline->is_clip_selected(link, true)) { - Selection ss; - ss.in = link->timeline_in; - ss.out = link->timeline_out; - ss.track = link->track; - panel_timeline->selections.append(ss); + switch (panel_timeline->tool) { + case TIMELINE_TOOL_POINTER: + case TIMELINE_TOOL_RIPPLE: + case TIMELINE_TOOL_SLIP: + case TIMELINE_TOOL_ROLLING: + case TIMELINE_TOOL_SLIDE: + { + if (track_resizing) { + track_resize_mouse_cache = event->pos().y(); + panel_timeline->moving_init = true; + } else { + if (clip_index >= 0) { + Clip* clip = sequence->get_clip(clip_index); + if (clip != NULL) { + if (panel_timeline->is_clip_selected(clip, true)) { + if (shift) { + // TODO if shift is down, deselect it + } + } else { + // if "shift" is not down + if (!shift) { + panel_timeline->selections.clear(); + } + + Selection s; + + s.in = clip->timeline_in; + s.out = clip->timeline_out; + s.track = clip->track; + panel_timeline->selections.append(s); + + if (panel_timeline->select_also_seeks) { + panel_timeline->seek(clip->timeline_in); + } + + // if alt is not down, select links + if (!(event->modifiers() & Qt::AltModifier)) { + for (int i=0;ilinked.size();i++) { + Clip* link = sequence->get_clip(clip->linked.at(i)); + if (!panel_timeline->is_clip_selected(link, true)) { + Selection ss; + ss.in = link->timeline_in; + ss.out = link->timeline_out; + ss.track = link->track; + panel_timeline->selections.append(ss); + } } } } } - } - panel_timeline->moving_init = true; - } else { - // if "shift" is not down - if (!shift) { - panel_timeline->selections.clear(); - } + panel_timeline->moving_init = true; + } else { + // if "shift" is not down + if (!shift) { + panel_timeline->selections.clear(); + } - panel_timeline->rect_select_init = true; + panel_timeline->rect_select_init = true; + } + panel_timeline->repaint_timeline(); } + } + break; + case TIMELINE_TOOL_EDIT: + if (panel_timeline->edit_tool_also_seeks) panel_timeline->seek(panel_timeline->drag_frame_start); + panel_timeline->selecting = true; + break; + case TIMELINE_TOOL_RAZOR: + { + panel_timeline->splitting = true; + panel_timeline->split_tracks.append(panel_timeline->drag_track_start); panel_timeline->repaint_timeline(); } - } - break; - case TIMELINE_TOOL_EDIT: - if (panel_timeline->edit_tool_also_seeks) panel_timeline->seek(panel_timeline->drag_frame_start); - panel_timeline->selecting = true; - break; - case TIMELINE_TOOL_RAZOR: - { - panel_timeline->splitting = true; - panel_timeline->split_tracks.append(panel_timeline->drag_track_start); - panel_timeline->repaint_timeline(); - } - break; + break; + } } } } void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { - bool alt = (event->modifiers() & Qt::AltModifier); + if (sequence != NULL) { + bool alt = (event->modifiers() & Qt::AltModifier); - if (event->button() == Qt::LeftButton) { - bool repaint = false; + if (event->button() == Qt::LeftButton) { + bool repaint = false; - if (panel_timeline->moving_proc) { - TimelineAction* ta = new TimelineAction(); + if (panel_timeline->moving_proc) { + TimelineAction* ta = new TimelineAction(); - // if we were RIPPLING, move all the clips - if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) { - long ripple_length, ripple_point; + // if we were RIPPLING, move all the clips + if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) { + long ripple_length, ripple_point; - // ripple_length becomes the length/number of frames we trimmed - // ripple point becomes the point to ripple (i.e. the point after or before which we move every clip) - const Ghost& first_ghost = panel_timeline->ghosts.at(0); - if (panel_timeline->trim_in_point) { - ripple_length = first_ghost.old_in - panel_timeline->ghosts.at(0).in; - ripple_point = first_ghost.old_in; - } else { - // if we're trimming an out-point - ripple_length = first_ghost.old_out - panel_timeline->ghosts.at(0).out; - ripple_point = first_ghost.old_out; - } - for (int i=0;ighosts.size();i++) { - const Ghost& g = panel_timeline->ghosts.at(i); - long comp_point; + // ripple_length becomes the length/number of frames we trimmed + // ripple point becomes the point to ripple (i.e. the point after or before which we move every clip) + const Ghost& first_ghost = panel_timeline->ghosts.at(0); if (panel_timeline->trim_in_point) { - comp_point = g.old_in; + ripple_length = first_ghost.old_in - panel_timeline->ghosts.at(0).in; + ripple_point = first_ghost.old_in; } else { - comp_point = g.old_out; + // if we're trimming an out-point + ripple_length = first_ghost.old_out - panel_timeline->ghosts.at(0).out; + ripple_point = first_ghost.old_out; } - if (ripple_point > comp_point) ripple_point = comp_point; - } - if (!panel_timeline->trim_in_point) ripple_length = -ripple_length; - panel_timeline->ripple(ta, ripple_point, ripple_length); - } - - if (panel_timeline->tool == TIMELINE_TOOL_POINTER && (event->modifiers() & Qt::AltModifier)) { // if holding alt, duplicate rather than move - // duplicate clips - QVector old_clips; - QVector new_clips; - QVector delete_areas; - for (int i=0;ighosts.size();i++) { - const Ghost& g = panel_timeline->ghosts.at(i); - if (g.old_in != g.in || g.old_out != g.out || g.track != g.old_track || g.clip_in != g.old_clip_in) { - // create copy of clip - Clip* c = sequence->get_clip(g.clip)->copy(); - - c->timeline_in = g.in; - c->timeline_out = g.out; - c->track = g.track; - - Selection s; - s.in = g.in; - s.out = g.out; - s.track = g.track; - delete_areas.append(s); - - old_clips.append(g.clip); - new_clips.append(c); + for (int i=0;ighosts.size();i++) { + const Ghost& g = panel_timeline->ghosts.at(i); + long comp_point; + if (panel_timeline->trim_in_point) { + comp_point = g.old_in; + } else { + comp_point = g.old_out; + } + if (ripple_point > comp_point) ripple_point = comp_point; } + if (!panel_timeline->trim_in_point) ripple_length = -ripple_length; + panel_timeline->ripple(ta, ripple_point, ripple_length); } - if (new_clips.size() > 0) { - panel_timeline->delete_areas_and_relink(ta, delete_areas); - // relink duplicated clips - panel_timeline->relink_clips_using_ids(old_clips, new_clips); - - for (int i=0;iadd_clips(sequence, new_clips); - } - } - } else { - // move clips - // TODO can we do this better than 3 consecutive for loops? - if (panel_timeline->tool == TIMELINE_TOOL_POINTER) { + if (panel_timeline->tool == TIMELINE_TOOL_POINTER && (event->modifiers() & Qt::AltModifier)) { // if holding alt, duplicate rather than move + // duplicate clips + QVector old_clips; + QVector new_clips; QVector delete_areas; for (int i=0;ighosts.size();i++) { - // step 1 - set clips that are moving to "undeletable" (to avoid step 2 deleting any part of them) const Ghost& g = panel_timeline->ghosts.at(i); + if (g.old_in != g.in || g.old_out != g.out || g.track != g.old_track || g.clip_in != g.old_clip_in) { + // create copy of clip + Clip* c = sequence->get_clip(g.clip)->copy(); - sequence->get_clip(g.clip)->undeletable = true; + c->timeline_in = g.in; + c->timeline_out = g.out; + c->track = g.track; - Selection s; - s.in = g.in; - s.out = g.out; - s.track = g.track; - delete_areas.append(s); + Selection s; + s.in = g.in; + s.out = g.out; + s.track = g.track; + delete_areas.append(s); + + old_clips.append(g.clip); + new_clips.append(c); + } } - panel_timeline->delete_areas_and_relink(ta, delete_areas); - for (int i=0;ighosts.size();i++) { - sequence->get_clip(panel_timeline->ghosts[i].clip)->undeletable = false; - } - } - for (int i=0;ighosts.size();i++) { - Ghost& g = panel_timeline->ghosts[i]; + if (new_clips.size() > 0) { + panel_timeline->delete_areas_and_relink(ta, delete_areas); - // step 3 - move clips - ta->increase_timeline_in(sequence, g.clip, g.in - g.old_in); - ta->increase_timeline_out(sequence, g.clip, g.out - g.old_out); - ta->increase_track(sequence, g.clip, g.track - g.old_track); - ta->increase_clip_in(sequence, g.clip, g.clip_in - g.old_clip_in); - } - } + // relink duplicated clips + panel_timeline->relink_clips_using_ids(old_clips, new_clips); - undo_stack.push(ta); - - panel_timeline->redraw_all_clips(true); - } else if (panel_timeline->selecting || panel_timeline->rect_select_proc) { - repaint = true; - } else if (panel_timeline->splitting) { - TimelineAction* ta = new TimelineAction(); - bool split = false; - for (int i=0;isplit_tracks.size();i++) { - int split_index = getClipIndexFromCoords(panel_timeline->drag_frame_start, panel_timeline->split_tracks.at(i)); - if (split_index > -1 && panel_timeline->split_clip_and_relink(ta, split_index, panel_timeline->drag_frame_start, !alt)) { - split = true; - } - } - if (split) { - undo_stack.push(ta); - panel_timeline->redraw_all_clips(true); - } else { - delete ta; - } - panel_timeline->split_cache.clear(); - } - - // remove duplicate selections - panel_timeline->clean_up_selections(panel_timeline->selections); - - // destroy all ghosts - panel_timeline->ghosts.clear(); - - // clear split tracks - panel_timeline->split_tracks.clear(); - - panel_timeline->selecting = false; - panel_timeline->moving_proc = false; - panel_timeline->moving_init = false; - panel_timeline->splitting = false; - panel_timeline->snapped = false; - panel_timeline->rect_select_init = false; - panel_timeline->rect_select_proc = false; - pre_clips.clear(); - post_clips.clear(); - - if (repaint) panel_timeline->repaint_timeline(); - - // SEND CLIPS TO EFFECT CONTROLS - // find out how many clips are selected - // limits to one video clip and one audio clip and only if they're linked - // one of these days it might be nice to have multiple clips in the effects panel - bool got_vclip = false; - bool got_aclip = false; - int vclip = -1; - int aclip = -1; - for (int i=0;iclip_count();i++) { - Clip* clip = sequence->get_clip(i); - if (clip != NULL && panel_timeline->is_clip_selected(clip, true)) { - if (clip->track < 0) { - if (got_vclip) { - vclip = -1; - } else { - vclip = i; - got_vclip = true; + for (int i=0;iadd_clips(sequence, new_clips); + } } } else { - if (got_aclip) { - aclip = -1; + // move clips + // TODO can we do this better than 3 consecutive for loops? + if (panel_timeline->tool == TIMELINE_TOOL_POINTER) { + QVector delete_areas; + for (int i=0;ighosts.size();i++) { + // step 1 - set clips that are moving to "undeletable" (to avoid step 2 deleting any part of them) + const Ghost& g = panel_timeline->ghosts.at(i); + + sequence->get_clip(g.clip)->undeletable = true; + + Selection s; + s.in = g.in; + s.out = g.out; + s.track = g.track; + delete_areas.append(s); + } + panel_timeline->delete_areas_and_relink(ta, delete_areas); + for (int i=0;ighosts.size();i++) { + sequence->get_clip(panel_timeline->ghosts[i].clip)->undeletable = false; + } + } + for (int i=0;ighosts.size();i++) { + Ghost& g = panel_timeline->ghosts[i]; + + // step 3 - move clips + ta->increase_timeline_in(sequence, g.clip, g.in - g.old_in); + ta->increase_timeline_out(sequence, g.clip, g.out - g.old_out); + ta->increase_track(sequence, g.clip, g.track - g.old_track); + ta->increase_clip_in(sequence, g.clip, g.clip_in - g.old_clip_in); + } + } + + undo_stack.push(ta); + + panel_timeline->redraw_all_clips(true); + } else if (panel_timeline->selecting || panel_timeline->rect_select_proc) { + repaint = true; + } else if (panel_timeline->splitting) { + TimelineAction* ta = new TimelineAction(); + bool split = false; + for (int i=0;isplit_tracks.size();i++) { + int split_index = getClipIndexFromCoords(panel_timeline->drag_frame_start, panel_timeline->split_tracks.at(i)); + if (split_index > -1 && panel_timeline->split_clip_and_relink(ta, split_index, panel_timeline->drag_frame_start, !alt)) { + split = true; + } + } + if (split) { + undo_stack.push(ta); + panel_timeline->redraw_all_clips(true); + } else { + delete ta; + } + panel_timeline->split_cache.clear(); + } + + // remove duplicate selections + panel_timeline->clean_up_selections(panel_timeline->selections); + + // destroy all ghosts + panel_timeline->ghosts.clear(); + + // clear split tracks + panel_timeline->split_tracks.clear(); + + panel_timeline->selecting = false; + panel_timeline->moving_proc = false; + panel_timeline->moving_init = false; + panel_timeline->splitting = false; + panel_timeline->snapped = false; + panel_timeline->rect_select_init = false; + panel_timeline->rect_select_proc = false; + pre_clips.clear(); + post_clips.clear(); + + if (repaint) panel_timeline->repaint_timeline(); + + // SEND CLIPS TO EFFECT CONTROLS + // find out how many clips are selected + // limits to one video clip and one audio clip and only if they're linked + // one of these days it might be nice to have multiple clips in the effects panel + bool got_vclip = false; + bool got_aclip = false; + int vclip = -1; + int aclip = -1; + for (int i=0;iclip_count();i++) { + Clip* clip = sequence->get_clip(i); + if (clip != NULL && panel_timeline->is_clip_selected(clip, true)) { + if (clip->track < 0) { + if (got_vclip) { + vclip = -1; + } else { + vclip = i; + got_vclip = true; + } } else { - aclip = i; - got_aclip = true; + if (got_aclip) { + aclip = -1; + } else { + aclip = i; + got_aclip = true; + } } } } - } - // check if aclip is linked to vclip - QVector selected_clips; - if (vclip != -1) selected_clips.append(vclip); - if (aclip != -1) selected_clips.append(aclip); - if (vclip != -1 && aclip != -1) { - bool found = false; - Clip* vclip_ref = sequence->get_clip(vclip); - for (int i=0;ilinked.size();i++) { - if (vclip_ref->linked.at(i) == aclip) { - found = true; - break; + // check if aclip is linked to vclip + QVector selected_clips; + if (vclip != -1) selected_clips.append(vclip); + if (aclip != -1) selected_clips.append(aclip); + if (vclip != -1 && aclip != -1) { + bool found = false; + Clip* vclip_ref = sequence->get_clip(vclip); + for (int i=0;ilinked.size();i++) { + if (vclip_ref->linked.at(i) == aclip) { + found = true; + break; + } + } + if (!found) { + // only display multiple clips if they're linked + selected_clips.clear(); } } - if (!found) { - // only display multiple clips if they're linked - selected_clips.clear(); - } + panel_effect_controls->set_clips(selected_clips); } - panel_effect_controls->set_clips(selected_clips); } } @@ -751,399 +816,409 @@ void TimelineWidget::update_ghosts(QPoint& mouse_pos) { } void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { - bool alt = (event->modifiers() & Qt::AltModifier); + if (sequence != NULL) { + bool alt = (event->modifiers() & Qt::AltModifier); - panel_timeline->cursor_frame = panel_timeline->getFrameFromScreenPoint(event->pos().x()); - panel_timeline->cursor_track = getTrackFromScreenPoint(event->pos().y()); + panel_timeline->cursor_frame = panel_timeline->getFrameFromScreenPoint(event->pos().x()); + panel_timeline->cursor_track = getTrackFromScreenPoint(event->pos().y()); - if (panel_timeline->tool == TIMELINE_TOOL_EDIT || panel_timeline->tool == TIMELINE_TOOL_RAZOR) { - panel_timeline->snap_to_clip(&panel_timeline->cursor_frame, !panel_timeline->edit_tool_also_seeks || !panel_timeline->selecting); - } - if (panel_timeline->selecting) { - int selection_count = 1 + qMax(panel_timeline->cursor_track, panel_timeline->drag_track_start) - qMin(panel_timeline->cursor_track, panel_timeline->drag_track_start) + panel_timeline->selection_offset; - if (panel_timeline->selections.size() != selection_count) { - panel_timeline->selections.resize(selection_count); - } - int minimum_selection_track = qMin(panel_timeline->cursor_track, panel_timeline->drag_track_start); - for (int i=panel_timeline->selection_offset;iselections[i]; - s.track = minimum_selection_track + i - panel_timeline->selection_offset; - long in = panel_timeline->drag_frame_start; - long out = panel_timeline->cursor_frame; - s.in = qMin(in, out); - s.out = qMax(in, out); - } - - // select linked clips too - if (panel_timeline->edit_tool_selects_links) { - for (int j=0;jclip_count();j++) { - Clip* c = sequence->get_clip(j); - for (int k=0;kselections.size();k++) { - const Selection& s = panel_timeline->selections.at(k); - if (!(c->timeline_in < s.in && c->timeline_out < s.in) && - !(c->timeline_in > s.out && c->timeline_out > s.out) && - c->track == s.track) { - - QVector linked_tracks = panel_timeline->get_tracks_of_linked_clips(j); - for (int k=0;kselections.size();l++) { - const Selection& test_sel = panel_timeline->selections.at(l); - if (test_sel.track == linked_tracks.at(k) && - test_sel.in == s.in && - test_sel.out == s.out) { - found = true; - break; - } - } - if (!found) { - Selection link_sel = {s.in, s.out, linked_tracks.at(k)}; - panel_timeline->selections.append(link_sel); - } - } - - break; - } - } - } + if (panel_timeline->tool == TIMELINE_TOOL_EDIT || panel_timeline->tool == TIMELINE_TOOL_RAZOR) { + panel_timeline->snap_to_clip(&panel_timeline->cursor_frame, !panel_timeline->edit_tool_also_seeks || !panel_timeline->selecting); } - - if (panel_timeline->edit_tool_also_seeks) { - panel_timeline->seek(qMin(panel_timeline->drag_frame_start, panel_timeline->cursor_frame)); - } else { - panel_timeline->repaint_timeline(); - } - } else if (panel_timeline->moving_init) { - if (track_resizing) { - int diff = track_resize_mouse_cache - event->pos().y(); - int new_height = track_resize_old_value; - if (bottom_align) { - new_height += diff; - } else { - new_height -= diff; + if (panel_timeline->selecting) { + int selection_count = 1 + qMax(panel_timeline->cursor_track, panel_timeline->drag_track_start) - qMin(panel_timeline->cursor_track, panel_timeline->drag_track_start) + panel_timeline->selection_offset; + if (panel_timeline->selections.size() != selection_count) { + panel_timeline->selections.resize(selection_count); + } + int minimum_selection_track = qMin(panel_timeline->cursor_track, panel_timeline->drag_track_start); + for (int i=panel_timeline->selection_offset;iselections[i]; + s.track = minimum_selection_track + i - panel_timeline->selection_offset; + long in = panel_timeline->drag_frame_start; + long out = panel_timeline->cursor_frame; + s.in = qMin(in, out); + s.out = qMax(in, out); } - if (new_height < TRACK_MIN_HEIGHT) new_height = TRACK_MIN_HEIGHT; - panel_timeline->calculate_track_height(track_target, new_height); - redraw_clips(); - } else if (panel_timeline->moving_proc) { - QPoint pos = event->pos(); - update_ghosts(pos); - } else { - // set up movement - // create ghosts - for (int i=0;iclip_count();i++) { - Clip* c = sequence->get_clip(i); - if (c != NULL && panel_timeline->is_clip_selected(c, true)) { - Ghost g; - g.clip = i; - g.trimming = (panel_timeline->trim_target > -1); - g.trim_in = panel_timeline->trim_in_point; - panel_timeline->ghosts.append(g); - } - } - int size = panel_timeline->ghosts.size(); - if (panel_timeline->tool == TIMELINE_TOOL_ROLLING) { - for (int i=0;iget_clip(panel_timeline->ghosts.at(i).clip); + // select linked clips too + if (panel_timeline->edit_tool_selects_links) { + for (int j=0;jclip_count();j++) { + Clip* c = sequence->get_clip(j); + for (int k=0;kselections.size();k++) { + const Selection& s = panel_timeline->selections.at(k); + if (!(c->timeline_in < s.in && c->timeline_out < s.in) && + !(c->timeline_in > s.out && c->timeline_out > s.out) && + c->track == s.track) { - // see if any ghosts are touching, in which case flip them - for (int k=0;kget_clip(panel_timeline->ghosts.at(k).clip); - if ((panel_timeline->trim_in_point && comp_clip->timeline_out == ghost_clip->timeline_in) || - (!panel_timeline->trim_in_point && comp_clip->timeline_in == ghost_clip->timeline_out)) { - panel_timeline->ghosts[k].trim_in = !panel_timeline->trim_in_point; - } - } - } - - // then look for other clips we're touching - for (int i=0;ighosts.at(i); - Clip* ghost_clip = sequence->get_clip(g.clip); - for (int j=0;jclip_count();j++) { - Clip* comp_clip = sequence->get_clip(j); - if (comp_clip->track == ghost_clip->track) { - if ((panel_timeline->trim_in_point && comp_clip->timeline_out == ghost_clip->timeline_in) || - (!panel_timeline->trim_in_point && comp_clip->timeline_in == ghost_clip->timeline_out)) { - // see if this clip is already selected, and if so just switch the trim_in + QVector linked_tracks = panel_timeline->get_tracks_of_linked_clips(j); + for (int k=0;kghosts.at(duplicate_ghost_index).clip == j) { + for (int l=0;lselections.size();l++) { + const Selection& test_sel = panel_timeline->selections.at(l); + if (test_sel.track == linked_tracks.at(k) && + test_sel.in == s.in && + test_sel.out == s.out) { found = true; break; } } - if (g.trim_in == panel_timeline->trim_in_point) { - if (!found) { - // add ghost for this clip with opposite trim_in - Ghost gh; - gh.clip = j; - gh.trimming = (panel_timeline->trim_target > -1); - gh.trim_in = !panel_timeline->trim_in_point; - panel_timeline->ghosts.append(gh); - } - } else { - if (found) { - panel_timeline->ghosts.removeAt(duplicate_ghost_index); - size--; - if (duplicate_ghost_index < i) i--; - } + if (!found) { + Selection link_sel = {s.in, s.out, linked_tracks.at(k)}; + panel_timeline->selections.append(link_sel); } } - } - } - } - } else if (panel_timeline->tool == TIMELINE_TOOL_SLIDE) { - for (int i=0;ighosts.at(i); - Clip* ghost_clip = sequence->get_clip(g.clip); - panel_timeline->ghosts[i].trimming = false; - for (int j=0;jclip_count();j++) { - Clip* c = sequence->get_clip(j); - if (c->track == ghost_clip->track) { - bool found = false; - for (int k=0;kghosts.at(k).clip == j) { - found = true; - break; - } - } - if (!found) { - bool is_in = (c->timeline_in == ghost_clip->timeline_out); - if (is_in || c->timeline_out == ghost_clip->timeline_in) { - Ghost gh; - gh.clip = j; - gh.trimming = true; - gh.trim_in = is_in; - panel_timeline->ghosts.append(gh); - } - } - } - } - } - } - init_ghosts(); - - // ripple edit prep - if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) { - QVector axis_ghosts; - for (int i=0;ighosts.size();i++) { - Clip* c = sequence->get_clip(panel_timeline->ghosts.at(i).clip); - bool found = false; - for (int j=0;jtrack == cc->track && - ((panel_timeline->trim_in_point && c->timeline_in < cc->timeline_in) || - (!panel_timeline->trim_in_point && c->timeline_out > cc->timeline_out))) { - axis_ghosts[j] = c; - found = true; break; } } - if (!found) { - axis_ghosts.append(c); - } } + } + if (panel_timeline->edit_tool_also_seeks) { + panel_timeline->seek(qMin(panel_timeline->drag_frame_start, panel_timeline->cursor_frame)); + } else { + panel_timeline->repaint_timeline(); + } + } else if (panel_timeline->moving_init) { + if (track_resizing) { + int diff = track_resize_mouse_cache - event->pos().y(); + int new_height = track_resize_old_value; + if (bottom_align) { + new_height += diff; + } else { + new_height -= diff; + } + if (new_height < TRACK_MIN_HEIGHT) new_height = TRACK_MIN_HEIGHT; + panel_timeline->calculate_track_height(track_target, new_height); + redraw_clips(); + } else if (panel_timeline->moving_proc) { + QPoint pos = event->pos(); + update_ghosts(pos); + } else { + // set up movement + // create ghosts for (int i=0;iclip_count();i++) { Clip* c = sequence->get_clip(i); - if (c != NULL && !panel_timeline->is_clip_selected(c, true)) { - for (int j=0;jtrim_in_point) ? axis->timeline_in : axis->timeline_out; - bool clip_is_pre = (c->timeline_in < comp_point); - QVector& clip_list = clip_is_pre ? pre_clips : post_clips; - bool found = false; - for (int k=0;ktrack == c->track) { - if (clip_is_pre == (c->timeline_in > cached->timeline_in)) { - clip_list[k] = c; + if (c != NULL && panel_timeline->is_clip_selected(c, true)) { + Ghost g; + g.clip = i; + g.trimming = (panel_timeline->trim_target > -1); + g.trim_in = panel_timeline->trim_in_point; + panel_timeline->ghosts.append(g); + } + } + + int size = panel_timeline->ghosts.size(); + if (panel_timeline->tool == TIMELINE_TOOL_ROLLING) { + for (int i=0;iget_clip(panel_timeline->ghosts.at(i).clip); + + // see if any ghosts are touching, in which case flip them + for (int k=0;kget_clip(panel_timeline->ghosts.at(k).clip); + if ((panel_timeline->trim_in_point && comp_clip->timeline_out == ghost_clip->timeline_in) || + (!panel_timeline->trim_in_point && comp_clip->timeline_in == ghost_clip->timeline_out)) { + panel_timeline->ghosts[k].trim_in = !panel_timeline->trim_in_point; + } + } + } + + // then look for other clips we're touching + for (int i=0;ighosts.at(i); + Clip* ghost_clip = sequence->get_clip(g.clip); + for (int j=0;jclip_count();j++) { + Clip* comp_clip = sequence->get_clip(j); + if (comp_clip->track == ghost_clip->track) { + if ((panel_timeline->trim_in_point && comp_clip->timeline_out == ghost_clip->timeline_in) || + (!panel_timeline->trim_in_point && comp_clip->timeline_in == ghost_clip->timeline_out)) { + // see if this clip is already selected, and if so just switch the trim_in + bool found = false; + int duplicate_ghost_index; + for (duplicate_ghost_index=0;duplicate_ghost_indexghosts.at(duplicate_ghost_index).clip == j) { + found = true; + break; + } + } + if (g.trim_in == panel_timeline->trim_in_point) { + if (!found) { + // add ghost for this clip with opposite trim_in + Ghost gh; + gh.clip = j; + gh.trimming = (panel_timeline->trim_target > -1); + gh.trim_in = !panel_timeline->trim_in_point; + panel_timeline->ghosts.append(gh); + } + } else { + if (found) { + panel_timeline->ghosts.removeAt(duplicate_ghost_index); + size--; + if (duplicate_ghost_index < i) i--; + } } - found = true; - break; } } - if (!found) { - clip_list.append(c); + } + } + } else if (panel_timeline->tool == TIMELINE_TOOL_SLIDE) { + for (int i=0;ighosts.at(i); + Clip* ghost_clip = sequence->get_clip(g.clip); + panel_timeline->ghosts[i].trimming = false; + for (int j=0;jclip_count();j++) { + Clip* c = sequence->get_clip(j); + if (c->track == ghost_clip->track) { + bool found = false; + for (int k=0;kghosts.at(k).clip == j) { + found = true; + break; + } + } + if (!found) { + bool is_in = (c->timeline_in == ghost_clip->timeline_out); + if (is_in || c->timeline_out == ghost_clip->timeline_in) { + Ghost gh; + gh.clip = j; + gh.trimming = true; + gh.trim_in = is_in; + panel_timeline->ghosts.append(gh); + } + } } } } } - } - panel_timeline->moving_proc = true; - } - panel_timeline->repaint_timeline(); - } else if (panel_timeline->splitting) { - int track_start = qMin(panel_timeline->cursor_track, panel_timeline->drag_track_start); - int track_end = qMax(panel_timeline->cursor_track, panel_timeline->drag_track_start); - int track_size = 1 + track_end - track_start; - panel_timeline->split_tracks.resize(track_size); - for (int i=0;isplit_tracks[i] = track_start + i; - } + init_ghosts(); - if (!alt) { - for (int i=0;idrag_frame_start, panel_timeline->split_tracks[i]); - if (clip_index > -1) { - QVector tracks = panel_timeline->get_tracks_of_linked_clips(clip_index); - for (int j=0;j track_end) { - panel_timeline->split_tracks.append(tracks.at(j)); - } - } - } - } - } - panel_timeline->repaint_timeline(); - } else if (panel_timeline->rect_select_init) { - if (panel_timeline->rect_select_proc) { - panel_timeline->rect_select_w = event->pos().x() - panel_timeline->rect_select_x; - panel_timeline->rect_select_h = event->pos().y() - panel_timeline->rect_select_y; - if (bottom_align) panel_timeline->rect_select_h -= height(); - - long frame_start = panel_timeline->getFrameFromScreenPoint(panel_timeline->rect_select_x); - long frame_end = panel_timeline->getFrameFromScreenPoint(event->pos().x()); - long frame_min = qMin(frame_start, frame_end); - long frame_max = qMax(frame_start, frame_end); - - int rsy = panel_timeline->rect_select_y; - if (bottom_align) rsy += height(); - int track_start = getTrackFromScreenPoint(rsy); - int track_end = getTrackFromScreenPoint(event->pos().y()); - int track_min = qMin(track_start, track_end); - int track_max = qMax(track_start, track_end); - - QVector selected_clips; - for (int i=0;iclip_count();i++) { - Clip* clip = sequence->get_clip(i); - if (clip != NULL && - clip->track >= track_min && - clip->track <= track_max && - !(clip->timeline_in < frame_min && clip->timeline_out < frame_min) && - !(clip->timeline_in > frame_max && clip->timeline_out > frame_max)) { - QVector session_clips; - session_clips.append(clip); - - if (!alt) { - for (int j=0;jlinked.size();j++) { - session_clips.append(sequence->get_clip(clip->linked.at(j))); - } - } - - for (int j=0;jtool == TIMELINE_TOOL_RIPPLE) { + QVector axis_ghosts; + for (int i=0;ighosts.size();i++) { + Clip* c = sequence->get_clip(panel_timeline->ghosts.at(i).clip); bool found = false; - Clip* c = session_clips.at(j); - for (int k=0;ktrack == cc->track && + ((panel_timeline->trim_in_point && c->timeline_in < cc->timeline_in) || + (!panel_timeline->trim_in_point && c->timeline_out > cc->timeline_out))) { + axis_ghosts[j] = c; found = true; break; } } if (!found) { - selected_clips.append(c); + axis_ghosts.append(c); + } + } + + for (int i=0;iclip_count();i++) { + Clip* c = sequence->get_clip(i); + if (c != NULL && !panel_timeline->is_clip_selected(c, true)) { + for (int j=0;jtrim_in_point) ? axis->timeline_in : axis->timeline_out; + bool clip_is_pre = (c->timeline_in < comp_point); + QVector& clip_list = clip_is_pre ? pre_clips : post_clips; + bool found = false; + for (int k=0;ktrack == c->track) { + if (clip_is_pre == (c->timeline_in > cached->timeline_in)) { + clip_list[k] = c; + } + found = true; + break; + } + } + if (!found) { + clip_list.append(c); + } + } + } + } + } + + panel_timeline->moving_proc = true; + } + panel_timeline->repaint_timeline(); + } else if (panel_timeline->splitting) { + int track_start = qMin(panel_timeline->cursor_track, panel_timeline->drag_track_start); + int track_end = qMax(panel_timeline->cursor_track, panel_timeline->drag_track_start); + int track_size = 1 + track_end - track_start; + panel_timeline->split_tracks.resize(track_size); + for (int i=0;isplit_tracks[i] = track_start + i; + } + + if (!alt) { + for (int i=0;idrag_frame_start, panel_timeline->split_tracks[i]); + if (clip_index > -1) { + QVector tracks = panel_timeline->get_tracks_of_linked_clips(clip_index); + for (int j=0;j track_end) { + panel_timeline->split_tracks.append(tracks.at(j)); + } } } } } - - panel_timeline->selections.resize(selected_clips.size() + panel_timeline->selection_offset); - for (int i=0;iselections[i+panel_timeline->selection_offset]; - Clip* clip = selected_clips.at(i); - s.old_in = s.in = clip->timeline_in; - s.old_out = s.out = clip->timeline_out; - s.old_track = s.track = clip->track; - } - panel_timeline->repaint_timeline(); - } else { - panel_timeline->rect_select_x = event->pos().x(); - panel_timeline->rect_select_y = event->pos().y(); - if (bottom_align) panel_timeline->rect_select_y -= height(); - panel_timeline->rect_select_w = 0; - panel_timeline->rect_select_h = 0; - panel_timeline->rect_select_proc = true; - } - } else if (panel_timeline->tool == TIMELINE_TOOL_POINTER || - panel_timeline->tool == TIMELINE_TOOL_RIPPLE || - panel_timeline->tool == TIMELINE_TOOL_ROLLING) { - track_resizing = false; + } else if (panel_timeline->rect_select_init) { + if (panel_timeline->rect_select_proc) { + panel_timeline->rect_select_w = event->pos().x() - panel_timeline->rect_select_x; + panel_timeline->rect_select_h = event->pos().y() - panel_timeline->rect_select_y; + if (bottom_align) panel_timeline->rect_select_h -= height(); - QPoint pos = event->pos(); + long frame_start = panel_timeline->getFrameFromScreenPoint(panel_timeline->rect_select_x); + long frame_end = panel_timeline->getFrameFromScreenPoint(event->pos().x()); + long frame_min = qMin(frame_start, frame_end); + long frame_max = qMax(frame_start, frame_end); - int lim = 5; - int mouse_track = getTrackFromScreenPoint(pos.y()); - long mouse_frame_lower = panel_timeline->getFrameFromScreenPoint(pos.x()-lim)-1; - long mouse_frame_upper = panel_timeline->getFrameFromScreenPoint(pos.x()+lim)+1; - bool found = false; - int closeness = INT_MAX; - for (int i=0;iclip_count();i++) { - Clip* c = sequence->get_clip(i); - if (c != NULL && c->track == mouse_track) { - 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; + int rsy = panel_timeline->rect_select_y; + if (bottom_align) rsy += height(); + int track_start = getTrackFromScreenPoint(rsy); + int track_end = getTrackFromScreenPoint(event->pos().y()); + int track_min = qMin(track_start, track_end); + int track_max = qMax(track_start, track_end); + + QVector selected_clips; + for (int i=0;iclip_count();i++) { + Clip* clip = sequence->get_clip(i); + if (clip != NULL && + clip->track >= track_min && + clip->track <= track_max && + !(clip->timeline_in < frame_min && clip->timeline_out < frame_min) && + !(clip->timeline_in > frame_max && clip->timeline_out > frame_max)) { + QVector session_clips; + session_clips.append(clip); + + if (!alt) { + for (int j=0;jlinked.size();j++) { + session_clips.append(sequence->get_clip(clip->linked.at(j))); + } + } + + for (int j=0;jtimeline_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 (found) { - setCursor(Qt::SizeHorCursor); - } else { - panel_timeline->trim_target = -1; - // look for track heights - found = false; - int track_y = 0; - for (int i=0;iget_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; - if (pos.y() > y_test_value-test_range && pos.y() < y_test_value+test_range) { - found = true; - track_resizing = true; - track_target = track; - track_resize_old_value = track_height; + panel_timeline->selections.resize(selected_clips.size() + panel_timeline->selection_offset); + for (int i=0;iselections[i+panel_timeline->selection_offset]; + Clip* clip = selected_clips.at(i); + s.old_in = s.in = clip->timeline_in; + s.old_out = s.out = clip->timeline_out; + s.old_track = s.track = clip->track; + } + + panel_timeline->repaint_timeline(); + } else { + panel_timeline->rect_select_x = event->pos().x(); + panel_timeline->rect_select_y = event->pos().y(); + if (bottom_align) panel_timeline->rect_select_y -= height(); + panel_timeline->rect_select_w = 0; + panel_timeline->rect_select_h = 0; + panel_timeline->rect_select_proc = true; + } + } else if (panel_timeline->tool == TIMELINE_TOOL_POINTER || + panel_timeline->tool == TIMELINE_TOOL_RIPPLE || + panel_timeline->tool == TIMELINE_TOOL_ROLLING) { + track_resizing = false; + + QPoint pos = event->pos(); + + int lim = 5; + int mouse_track = getTrackFromScreenPoint(pos.y()); + long mouse_frame_lower = panel_timeline->getFrameFromScreenPoint(pos.x()-lim)-1; + long mouse_frame_upper = panel_timeline->getFrameFromScreenPoint(pos.x()+lim)+1; + bool found = false; + bool cursor_contains_clip = false; + int closeness = INT_MAX; + for (int i=0;iclip_count();i++) { + Clip* c = sequence->get_clip(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->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 (found) { - setCursor(Qt::SizeVerCursor); + setCursor(Qt::SizeHorCursor); + } else { + panel_timeline->trim_target = -1; + + // look for track heights + int track_y = 0; + for (int i=0;iget_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; + if (pos.y() > y_test_value-test_range && pos.y() < y_test_value+test_range) { + // if track lines are hidden, only resize track if a clip is already there + if (show_track_lines || cursor_contains_clip) { + found = true; + track_resizing = true; + track_target = track; + track_resize_old_value = track_height; + } + break; + } + } + + if (found) { + setCursor(Qt::SizeVerCursor); + } else { + unsetCursor(); + } + } + } else if (panel_timeline->tool == TIMELINE_TOOL_EDIT || panel_timeline->tool == TIMELINE_TOOL_RAZOR) { + // redraw because we have a cursor + panel_timeline->repaint_timeline(); + } else if (panel_timeline->tool == TIMELINE_TOOL_SLIP) { + if (getClipIndexFromCoords(panel_timeline->cursor_frame, panel_timeline->cursor_track) > -1) { + setCursor(Qt::SizeHorCursor); } else { unsetCursor(); } - } - } else if (panel_timeline->tool == TIMELINE_TOOL_EDIT || panel_timeline->tool == TIMELINE_TOOL_RAZOR) { - // redraw because we have a cursor - panel_timeline->repaint_timeline(); - } else if (panel_timeline->tool == TIMELINE_TOOL_SLIP) { - if (getClipIndexFromCoords(panel_timeline->cursor_frame, panel_timeline->cursor_track) > -1) { - setCursor(Qt::SizeHorCursor); - } else { - unsetCursor(); } } } diff --git a/ui/timelinewidget.h b/ui/timelinewidget.h index 8e49e7327..0d7793f09 100644 --- a/ui/timelinewidget.h +++ b/ui/timelinewidget.h @@ -57,6 +57,12 @@ private: QPixmap clip_pixmap; // QPixmap selection_pixmap; + int predicted_video_width; + int predicted_video_height; + double predicted_new_frame_rate; + int predicted_audio_freq; + int predicted_audio_layout; + signals: public slots: