diff --git a/io/previewgenerator.cpp b/io/previewgenerator.cpp index 0e2544cf2..dae02d0dd 100644 --- a/io/previewgenerator.cpp +++ b/io/previewgenerator.cpp @@ -87,7 +87,6 @@ void PreviewGenerator::run() { 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); - qDebug() << dstW; uint8_t* data = new uint8_t[dstW*dstH*3]; sws_ctx = sws_getContext( diff --git a/mainwindow.cpp b/mainwindow.cpp index 8f14c4e1f..56d0bbd1e 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -19,9 +19,14 @@ #include #include #include +#include +#include #define OLIVE_FILE_FILTER "Olive Project (*.ove)" +QString autorecovery_filename; +QTimer autorecovery_timer; + void MainWindow::setup_layout() { panel_project->show(); panel_effect_controls->show(); @@ -77,10 +82,34 @@ MainWindow::MainWindow(QWidget *parent) : panel_timeline = new Timeline(this); setup_layout(); + + QString data_dir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + if (!data_dir.isEmpty()) { + QDir dir(data_dir); + dir.mkpath("."); + if (dir.exists()) { + autorecovery_filename = data_dir + "/autorecovery.ove"; + if (QFile::exists(autorecovery_filename)) { + if (QMessageBox::question(this, "Auto-recovery", "Olive didn't close properly and an autorecovery file was detected. Would you like to open it?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) { + project_url = autorecovery_filename; + panel_project->load_project(); + } + } + autorecovery_timer.setInterval(60000); + QObject::connect(&autorecovery_timer, SIGNAL(timeout()), this, SLOT(autorecover_interval())); + autorecovery_timer.start(); + } + } } -MainWindow::~MainWindow() -{ +MainWindow::~MainWindow() { + QString data_dir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + if (!data_dir.isEmpty() && !autorecovery_filename.isEmpty()) { + if (QFile::exists(autorecovery_filename)) { + QFile::remove(autorecovery_filename); + } + } + delete ui; delete panel_project; @@ -219,6 +248,16 @@ void MainWindow::on_action_Paste_triggered() } } +void MainWindow::autorecover_interval() { + bool old_changed = project_changed; + QString old_filename = project_url; + project_url = autorecovery_filename; + qDebug() << "[INFO] Auto-recovery project saved"; + panel_project->save_project(); + project_url = old_filename; + project_changed = old_changed; +} + bool MainWindow::save_project_as() { QString fn = QFileDialog::getSaveFileName(this, "Save Project As...", "", OLIVE_FILE_FILTER); if (!fn.isEmpty()) { diff --git a/mainwindow.h b/mainwindow.h index d60867fcd..d3cfd9fe9 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -105,6 +105,8 @@ private slots: void on_actionGo_to_Next_Cut_triggered(); + void autorecover_interval(); + private: Ui::MainWindow *ui; void setup_layout(); diff --git a/olive.pro.user b/olive.pro.user index 38906f29f..caffec19e 100644 --- a/olive.pro.user +++ b/olive.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/panels/project.cpp b/panels/project.cpp index c9ff35f2a..af51eea99 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -418,6 +418,8 @@ void Project::load_project() { qDebug() << "[ERROR] Error parsing XML." << stream.error(); } + panel_timeline->redraw_all_clips(); + project_changed = false; } diff --git a/ui/timelineheader.cpp b/ui/timelineheader.cpp index fc5c7e5a0..498e8671e 100644 --- a/ui/timelineheader.cpp +++ b/ui/timelineheader.cpp @@ -12,6 +12,7 @@ TimelineHeader::TimelineHeader(QWidget *parent) : QWidget(parent) { dragging = false; + setCursor(Qt::ArrowCursor); } void set_playhead(QMouseEvent* event) { diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index 53de14d29..77804092d 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -18,7 +18,8 @@ #include #include #include -#include +#include +#include #include TimelineWidget::TimelineWidget(QWidget *parent) : QWidget(parent) @@ -28,6 +29,15 @@ TimelineWidget::TimelineWidget(QWidget *parent) : QWidget(parent) track_height = 80; setAcceptDrops(true); + + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu(const QPoint&))); +} + +void TimelineWidget::show_context_menu(const QPoint& pos) { + QMenu menu(this); + menu.addAction("heck!"); + menu.exec(mapToGlobal(pos)); } bool same_sign(int a, int b) { @@ -156,185 +166,189 @@ void TimelineWidget::mouseDoubleClickEvent(QMouseEvent *event) { } void TimelineWidget::mousePressEvent(QMouseEvent *event) { - 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()); - } + 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); + int clip_index = panel_timeline->trim_target; + if (clip_index == -1) clip_index = getClipIndexFromCoords(panel_timeline->drag_frame_start, panel_timeline->drag_track_start); - switch (panel_timeline->tool) { - case TIMELINE_TOOL_POINTER: - case TIMELINE_TOOL_RIPPLE: - case TIMELINE_TOOL_SLIP: - { - if (clip_index >= 0) { - if (panel_timeline->is_clip_selected(sequence->get_clip(clip_index))) { - // TODO if shift is down, deselect it - } else { - // if "shift" is not down - if (!(event->modifiers() & Qt::ShiftModifier)) { - panel_timeline->selections.clear(); - } + switch (panel_timeline->tool) { + case TIMELINE_TOOL_POINTER: + case TIMELINE_TOOL_RIPPLE: + case TIMELINE_TOOL_SLIP: + { + if (clip_index >= 0) { + if (panel_timeline->is_clip_selected(sequence->get_clip(clip_index))) { + // TODO if shift is down, deselect it + } else { + // if "shift" is not down + if (!(event->modifiers() & Qt::ShiftModifier)) { + panel_timeline->selections.clear(); + } - Clip* clip = sequence->get_clip(clip_index); - panel_timeline->selections.append({clip->timeline_in, clip->timeline_out, clip->track}); + Clip* clip = sequence->get_clip(clip_index); + panel_timeline->selections.append({clip->timeline_in, clip->timeline_out, clip->track}); - // if alt is not down, select links - if (!(event->modifiers() & Qt::AltModifier)) { - for (int i=0;ilinked.size();i++) { - Clip* link = clip->linked.at(i); - if (!panel_timeline->is_clip_selected(link)) { - panel_timeline->selections.append({link->timeline_in, link->timeline_out, link->track}); + // if alt is not down, select links + if (!(event->modifiers() & Qt::AltModifier)) { + for (int i=0;ilinked.size();i++) { + Clip* link = clip->linked.at(i); + if (!panel_timeline->is_clip_selected(link)) { + panel_timeline->selections.append({link->timeline_in, link->timeline_out, link->track}); + } } } } - } - panel_timeline->moving_init = true; - } else { - panel_timeline->selections.clear(); - } - panel_timeline->repaint_timeline(); - } - break; - case TIMELINE_TOOL_EDIT: - panel_timeline->seek(panel_timeline->drag_frame_start); - panel_timeline->selecting = true; - break; - case TIMELINE_TOOL_RAZOR: - { - if (clip_index >= 0) { - panel_timeline->split_clip_and_relink(sequence->get_clip(clip_index), panel_timeline->drag_frame_start, !(event->modifiers() & Qt::AltModifier)); - } - panel_timeline->splitting = true; - panel_timeline->redraw_all_clips(); - } - break; - } + panel_timeline->moving_init = true; + } else { + panel_timeline->selections.clear(); + } + panel_timeline->repaint_timeline(); + } + break; + case TIMELINE_TOOL_EDIT: + panel_timeline->seek(panel_timeline->drag_frame_start); + panel_timeline->selecting = true; + break; + case TIMELINE_TOOL_RAZOR: + { + if (clip_index >= 0) { + panel_timeline->split_clip_and_relink(sequence->get_clip(clip_index), panel_timeline->drag_frame_start, !(event->modifiers() & Qt::AltModifier)); + } + panel_timeline->splitting = true; + panel_timeline->redraw_all_clips(); + } + break; + } + } } void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { - if (panel_timeline->moving_proc) { - if (event->modifiers() & Qt::AltModifier) { // if holding alt, duplicate rather than move - // duplicate clips - QVector copy_clips; - QVector delete_areas; - for (int i=0;ighosts.size();i++) { - const Ghost& g = panel_timeline->ghosts.at(i); + if (event->button() == Qt::LeftButton) { + if (panel_timeline->moving_proc) { + if (event->modifiers() & Qt::AltModifier) { // if holding alt, duplicate rather than move + // duplicate clips + QVector copy_clips; + QVector delete_areas; + for (int i=0;ighosts.size();i++) { + const Ghost& g = panel_timeline->ghosts.at(i); - Clip* c = g.clip->copy(); + Clip* c = g.clip->copy(); - c->timeline_in = g.in; - c->timeline_out = g.out; - c->track = g.track; + c->timeline_in = g.in; + c->timeline_out = g.out; + c->track = g.track; - copy_clips.append(c); - } - panel_timeline->delete_areas_and_relink(delete_areas); - for (int i=0;iadd_clip(copy_clips.at(i)); - } - } else { - // move clips - // TODO can we do this better than 3 consecutive for loops? - 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) - panel_timeline->ghosts[i].clip->undeletable = true; - } - // step 2 - delete areas - QVector delete_areas; - for (int i=0;ighosts.size();i++) { - const Ghost& g = panel_timeline->ghosts.at(i); - - if (panel_timeline->tool == TIMELINE_TOOL_POINTER) { + copy_clips.append(c); + } + panel_timeline->delete_areas_and_relink(delete_areas); + for (int i=0;iadd_clip(copy_clips.at(i)); + } + } else { + // move clips + // TODO can we do this better than 3 consecutive for loops? + 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) + panel_timeline->ghosts[i].clip->undeletable = true; + } + // step 2 - delete areas + QVector delete_areas; + for (int i=0;ighosts.size();i++) { + const Ghost& g = panel_timeline->ghosts.at(i); + + if (panel_timeline->tool == TIMELINE_TOOL_POINTER) { + // step 2 - delete anything that exists in area that clip is moving to + // note: ripples are non-destructive so this is pointer-tool exclusive + delete_areas.append({g.in, g.out, g.track}); + } + } + panel_timeline->delete_areas_and_relink(delete_areas); + for (int i=0;ighosts.size();i++) { + Ghost& g = panel_timeline->ghosts[i]; + + // step 3 - move clips + g.clip->timeline_in = g.in; + g.clip->timeline_out = g.out; + g.clip->track = g.track; + g.clip->clip_in = g.clip_in; + } + for (int i=0;ighosts.size();i++) { + // step 4 - set clips back to deletable + panel_timeline->ghosts[i].clip->undeletable = false; } } - panel_timeline->delete_areas_and_relink(delete_areas); - for (int i=0;ighosts.size();i++) { - Ghost& g = panel_timeline->ghosts[i]; - // step 3 - move clips - g.clip->timeline_in = g.in; - g.clip->timeline_out = g.out; - g.clip->track = g.track; - g.clip->clip_in = g.clip_in; - } - for (int i=0;ighosts.size();i++) { - // step 4 - set clips back to deletable - panel_timeline->ghosts[i].clip->undeletable = false; - } - } + // ripple ops + if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) { + long ripple_length, ripple_point; + if (panel_timeline->trim_in) { + ripple_length = panel_timeline->ghosts.at(0).old_in - panel_timeline->ghosts.at(0).in; + ripple_point = (ripple_length < 0) ? panel_timeline->ghosts.at(0).old_in : panel_timeline->ghosts.at(0).in; + } else { + ripple_length = panel_timeline->ghosts.at(0).old_out - panel_timeline->ghosts.at(0).out; + ripple_point = (ripple_length < 0) ? panel_timeline->ghosts.at(0).old_out : panel_timeline->ghosts.at(0).out; + } + for (int i=0;ighosts.size();i++) { + long comp_point; + if (panel_timeline->trim_in) { + comp_point = (ripple_length < 0) ? panel_timeline->ghosts.at(i).old_in : panel_timeline->ghosts.at(i).in; + } else { + comp_point = (ripple_length < 0) ? panel_timeline->ghosts.at(i).old_out : panel_timeline->ghosts.at(i).out; + } + if (ripple_point > comp_point) ripple_point = comp_point; + } + if (panel_timeline->trim_in) { + panel_timeline->ripple(ripple_point, ripple_length); + } else { + panel_timeline->ripple(ripple_point, -ripple_length); + } + } - // ripple ops - if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) { - long ripple_length, ripple_point; - if (panel_timeline->trim_in) { - ripple_length = panel_timeline->ghosts.at(0).old_in - panel_timeline->ghosts.at(0).in; - ripple_point = (ripple_length < 0) ? panel_timeline->ghosts.at(0).old_in : panel_timeline->ghosts.at(0).in; - } else { - ripple_length = panel_timeline->ghosts.at(0).old_out - panel_timeline->ghosts.at(0).out; - ripple_point = (ripple_length < 0) ? panel_timeline->ghosts.at(0).old_out : panel_timeline->ghosts.at(0).out; - } - for (int i=0;ighosts.size();i++) { - long comp_point; - if (panel_timeline->trim_in) { - comp_point = (ripple_length < 0) ? panel_timeline->ghosts.at(i).old_in : panel_timeline->ghosts.at(i).in; - } else { - comp_point = (ripple_length < 0) ? panel_timeline->ghosts.at(i).old_out : panel_timeline->ghosts.at(i).out; - } - if (ripple_point > comp_point) ripple_point = comp_point; - } - if (panel_timeline->trim_in) { - panel_timeline->ripple(ripple_point, ripple_length); - } else { - panel_timeline->ripple(ripple_point, -ripple_length); - } - } + panel_timeline->redraw_all_clips(); + } - panel_timeline->redraw_all_clips(); - } + // destroy all ghosts + panel_timeline->ghosts.clear(); - // destroy all ghosts - panel_timeline->ghosts.clear(); + panel_timeline->selecting = false; + panel_timeline->moving_proc = false; + panel_timeline->moving_init = false; + panel_timeline->splitting = false; + panel_timeline->snapped = false; + pre_clips.clear(); + post_clips.clear(); - panel_timeline->selecting = false; - panel_timeline->moving_proc = false; - panel_timeline->moving_init = false; - panel_timeline->splitting = false; - panel_timeline->snapped = false; - pre_clips.clear(); - post_clips.clear(); - - // find out how many clips are selected - bool single_select = false; - int selected_clip = 0; - for (int i=0;iclip_count();i++) { - if (panel_timeline->is_clip_selected(sequence->get_clip(i))) { - if (!single_select) { - // found ONE selected clip - selected_clip = i; - single_select = true; - } else { - // more than one clip is selected - single_select = false; - break; - } - } - } - if (single_select) { - panel_effect_controls->set_clip(sequence->get_clip(selected_clip)); - } else { - panel_effect_controls->set_clip(NULL); - } + // find out how many clips are selected + bool single_select = false; + int selected_clip = 0; + for (int i=0;iclip_count();i++) { + if (panel_timeline->is_clip_selected(sequence->get_clip(i))) { + if (!single_select) { + // found ONE selected clip + selected_clip = i; + single_select = true; + } else { + // more than one clip is selected + single_select = false; + break; + } + } + } + if (single_select) { + panel_effect_controls->set_clip(sequence->get_clip(selected_clip)); + } else { + panel_effect_controls->set_clip(NULL); + } + } } void TimelineWidget::init_ghosts() { @@ -762,7 +776,7 @@ void TimelineWidget::redraw_clips() { // Draw clips int panel_width = panel_timeline->getScreenPointFromFrame(sequence->getEndFrame()) + 100; - if (minimumWidth() != panel_width) { + if (minimumWidth() != panel_width || clip_pixmap.height() != height()) { setMinimumWidth(panel_width); clip_pixmap = QPixmap(panel_width, height()); } diff --git a/ui/timelinewidget.h b/ui/timelinewidget.h index 15cf9990d..7201bbf84 100644 --- a/ui/timelinewidget.h +++ b/ui/timelinewidget.h @@ -53,7 +53,7 @@ signals: public slots: private slots: - + void show_context_menu(const QPoint& pos); }; #endif // TIMELINEWIDGET_H