diff --git a/mainwindow.cpp b/mainwindow.cpp index bcca7a9fa..6bdb414ed 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -206,6 +206,7 @@ MainWindow::MainWindow(QWidget *parent) : autorecovery_filename = data_dir + "/autorecovery.ove"; if (QFile::exists(autorecovery_filename)) { if (QMessageBox::question(NULL, "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) { + enable_launch_with_project = false; open_project_worker(autorecovery_filename, true); } } @@ -258,12 +259,16 @@ void MainWindow::delete_slot() { panel_project->delete_selected_media(); } else if (panel_effect_controls->keyframe_focus()) { panel_effect_controls->delete_selected_keyframes(); + } else if (panel_graph_editor->view_is_focused()) { + panel_graph_editor->delete_selected_keys(); } } void MainWindow::select_all() { if (panel_timeline->focused()) { panel_timeline->select_all(); + } else if (panel_graph_editor->view_is_focused()) { + panel_graph_editor->select_all(); } } diff --git a/panels/grapheditor.cpp b/panels/grapheditor.cpp index c6e8500f6..2cb44f673 100644 --- a/panels/grapheditor.cpp +++ b/panels/grapheditor.cpp @@ -202,6 +202,14 @@ bool GraphEditor::view_is_focused() { return view->hasFocus() || header->hasFocus(); } +void GraphEditor::delete_selected_keys() { + view->delete_selected_keys(); +} + +void GraphEditor::select_all() { + view->select_all(); +} + void GraphEditor::set_key_button_enabled(bool e, int type) { linear_button->setEnabled(e); linear_button->setChecked(type == KEYFRAME_TYPE_LINEAR); diff --git a/panels/grapheditor.h b/panels/grapheditor.h index 16c71d23a..1a5277b58 100644 --- a/panels/grapheditor.h +++ b/panels/grapheditor.h @@ -18,7 +18,9 @@ public: GraphEditor(QWidget* parent = 0); void update_panel(); void set_row(EffectRow* r); - bool view_is_focused(); + bool view_is_focused(); + void delete_selected_keys(); + void select_all(); private: GraphView* view; TimelineHeader* header; diff --git a/project/effect.h b/project/effect.h index a7210a3de..290fa6cc7 100644 --- a/project/effect.h +++ b/project/effect.h @@ -23,7 +23,6 @@ class QXmlStreamWriter; class Effect; class EffectRow; class CheckboxEx; -class KeyframeDelete; struct EffectMeta { QString name; diff --git a/project/effectrow.h b/project/effectrow.h index a91171545..8326cb1f2 100644 --- a/project/effectrow.h +++ b/project/effectrow.h @@ -8,7 +8,6 @@ class Effect; class QGridLayout; class EffectField; class QLabel; -class KeyframeDelete; class QPushButton; class ComboAction; class QHBoxLayout; @@ -23,8 +22,8 @@ public: EffectField* add_field(int type, const QString &id, int colspan = 1); EffectField* field(int i); int fieldCount(); - void set_keyframe_now(ComboAction *ca); - void delete_keyframe_at_time(ComboAction *ca, long time); + void set_keyframe_now(ComboAction *ca); + void delete_keyframe_at_time(ComboAction *ca, long time); ClickableLabel* label; Effect* parent_effect; bool savable; diff --git a/project/keyframe.cpp b/project/keyframe.cpp index 3d12220df..09b73be75 100644 --- a/project/keyframe.cpp +++ b/project/keyframe.cpp @@ -1,5 +1,10 @@ #include "keyframe.h" +#include + +#include "effectfield.h" +#include "undo.h" +#include "panels/panels.h" EffectKeyframe::EffectKeyframe() { pre_handle_x = -40; @@ -7,3 +12,35 @@ EffectKeyframe::EffectKeyframe() { post_handle_x = 40; post_handle_y = 0; } + +void delete_keyframes(QVector& selected_key_fields, QVector &selected_keys) { + QVector fields; + QVector key_indices; + + for (int i=0;i 0) { + ComboAction* ca = new ComboAction(); + for (int i=0;iappend(new KeyframeDelete(fields.at(i), key_indices.at(i))); + } + undo_stack.push(ca); + selected_keys.clear(); + selected_key_fields.clear(); + update_ui(false); + } +} diff --git a/project/keyframe.h b/project/keyframe.h index 7974a8a1b..fd7e4ac0f 100644 --- a/project/keyframe.h +++ b/project/keyframe.h @@ -3,6 +3,8 @@ #include +class EffectField; + class EffectKeyframe { public: EffectKeyframe(); @@ -18,4 +20,6 @@ public: double post_handle_y; }; +void delete_keyframes(QVector &selected_key_fields, QVector &selected_keys); + #endif // KEYFRAME_H diff --git a/ui/graphview.cpp b/ui/graphview.cpp index ec535fc10..3f226ad8c 100644 --- a/ui/graphview.cpp +++ b/ui/graphview.cpp @@ -56,6 +56,18 @@ GraphView::GraphView(QWidget* parent) : void GraphView::show_context_menu(const QPoint& pos) { QMenu menu(this); + QAction* zoom_to_selection = menu.addAction("Zoom to Selection"); + if (selected_keys.size() == 0) { + zoom_to_selection->setEnabled(false); + } else { + connect(zoom_to_selection, SIGNAL(triggered(bool)), this, SLOT(set_view_to_selection())); + } + + QAction* zoom_to_all = menu.addAction("Zoom to Show All"); + connect(zoom_to_all, SIGNAL(triggered(bool)), this, SLOT(set_view_to_all())); + + menu.addSeparator(); + QAction* reset_action = menu.addAction("Reset View"); connect(reset_action, SIGNAL(triggered(bool)), this, SLOT(reset_view())); @@ -70,6 +82,61 @@ void GraphView::reset_view() { update(); } +void GraphView::set_view_to_selection() { + if (selected_keys.size() > 0) { + long min_time = LONG_MAX; + long max_time = LONG_MIN; + double min_dbl = DBL_MAX; + double max_dbl = DBL_MIN; + for (int i=0;ifield(selected_keys_fields.at(i))->keyframes.at(selected_keys.at(i)); + min_time = qMin(key.time, min_time); + max_time = qMax(key.time, max_time); + min_dbl = qMin(key.data.toDouble(), min_dbl); + max_dbl = qMax(key.data.toDouble(), max_dbl); + } + set_view_to_rect(min_time, min_dbl, max_time, max_dbl); + } +} + +void GraphView::set_view_to_all() { + bool can_set = false; + + long min_time = LONG_MAX; + long max_time = LONG_MIN; + double min_dbl = DBL_MAX; + double max_dbl = DBL_MIN; + for (int i=0;ifieldCount();i++) { + for (int j=0;jfield(i)->keyframes.size();j++) { + const EffectKeyframe& key = row->field(i)->keyframes.at(j); + min_time = qMin(key.time, min_time); + max_time = qMax(key.time, max_time); + min_dbl = qMin(key.data.toDouble(), min_dbl); + max_dbl = qMax(key.data.toDouble(), max_dbl); + can_set = true; + } + } + if (can_set) { + set_view_to_rect(min_time, min_dbl, max_time, max_dbl); + } +} + +void GraphView::set_view_to_rect(int x1, double y1, int x2, double y2) { + double padding = 1.5; + double inverse_padding = 1.0/padding; + double x_diff = double(x2 - x1); + double y_diff = (y2 - y1); + double x_diff_padded = x_diff*padding; + double y_diff_padded = y_diff*padding; + set_zoom(qMin(double(width()) / x_diff_padded, double(height()) / y_diff_padded)); + + set_scroll_x(qRound((double(x1) - ((x_diff_padded-x_diff)/2))*zoom)); + set_scroll_y(qRound((double(y1) - ((y_diff_padded-y_diff)/2))*zoom)); + + //set_scroll_y(height() - y1); + +} + void GraphView::draw_line_text(QPainter &p, bool vert, int line_no, int line_pos, int next_line_pos) { // draws last line's text QString str = QString::number(line_no*GRAPH_SIZE); @@ -520,12 +587,39 @@ void GraphView::set_field_visibility(int field, bool b) { update(); } +void GraphView::delete_selected_keys() { + if (row != NULL) { + QVector fields; + for (int i=0;ifield(selected_keys_fields.at(i))); + } + delete_keyframes(fields, selected_keys); + } +} + +void GraphView::select_all() { + if (row != NULL) { + selected_keys.clear(); + selected_keys_fields.clear(); + for (int i=0;ifieldCount();i++) { + EffectField* field = row->field(i); + for (int j=0;jkeyframes.size();j++) { + selected_keys.append(j); + selected_keys_fields.append(i); + } + } + selection_update(); + } +} + void GraphView::set_scroll_x(int s) { x_scroll = s; emit x_scroll_changed(x_scroll); } void GraphView::set_scroll_y(int s) { + dout << s << height() << zoom; + y_scroll = s; emit y_scroll_changed(y_scroll); } diff --git a/ui/graphview.h b/ui/graphview.h index 5d1246269..e4646cb66 100644 --- a/ui/graphview.h +++ b/ui/graphview.h @@ -23,6 +23,9 @@ public: void set_selected_keyframe_type(int type); void set_field_visibility(int field, bool b); + + void delete_selected_keys(); + void select_all(); signals: void x_scroll_changed(int); void y_scroll_changed(int); @@ -75,6 +78,9 @@ private: private slots: void show_context_menu(const QPoint& pos); void reset_view(); + void set_view_to_selection(); + void set_view_to_all(); + void set_view_to_rect(int x1, double y1, int x2, double y2); }; #endif // GRAPHVIEW_H diff --git a/ui/keyframedrawing.cpp b/ui/keyframedrawing.cpp index 07d515957..53229e46c 100644 --- a/ui/keyframedrawing.cpp +++ b/ui/keyframedrawing.cpp @@ -4,10 +4,14 @@ #define KEYFRAME_POINT_COUNT 4 -void draw_keyframe(QPainter &p, int type, int x, int y, bool darker) { - int color = (darker) ? 100 : 160; +void draw_keyframe(QPainter &p, int type, int x, int y, bool darker, int r, int g, int b) { + if (darker) { + r *= 0.625; + g *= 0.625; + b *= 0.625; + } p.setPen(QColor(0, 0, 0)); - p.setBrush(QColor(color, color, color)); + p.setBrush(QColor(r, g, b)); switch (type) { case KEYFRAME_TYPE_LINEAR: @@ -24,5 +28,5 @@ void draw_keyframe(QPainter &p, int type, int x, int y, bool darker) { break; } - p.setBrush(Qt::NoBrush); + p.setBrush(Qt::NoBrush); } diff --git a/ui/keyframedrawing.h b/ui/keyframedrawing.h index c09ae2626..c8c60e9e3 100644 --- a/ui/keyframedrawing.h +++ b/ui/keyframedrawing.h @@ -4,7 +4,8 @@ #include #define KEYFRAME_SIZE 6 +#define KEYFRAME_COLOR 160 -void draw_keyframe(QPainter &p, int type, int x, int y, bool darker); +void draw_keyframe(QPainter &p, int type, int x, int y, bool darker, int r = KEYFRAME_COLOR, int g = KEYFRAME_COLOR, int b = KEYFRAME_COLOR); #endif // KEYFRAMEDRAWING_H diff --git a/ui/keyframeview.cpp b/ui/keyframeview.cpp index bbe8d7dac..ddebcf1c4 100644 --- a/ui/keyframeview.cpp +++ b/ui/keyframeview.cpp @@ -16,6 +16,7 @@ #include "ui/clickablelabel.h" #include "ui/resizablescrollbar.h" #include "ui/rectangleselect.h" +#include "project/keyframe.h" #include #include @@ -165,23 +166,7 @@ void KeyframeView::update_keys() { } void KeyframeView::delete_selected_keyframes() { - ComboAction* ca = new ComboAction(); - bool del = false; - for (int i=0;iappend(new KeyframeDelete(selected_fields.at(i), selected_keyframes.at(i))); - del = true; - } - if (del) { - undo_stack.push(ca); - - selected_keyframes.clear(); - selected_fields.clear(); - update_keys(); - panel_sequence_viewer->viewer_widget->update(); - } else { - delete ca; - } + delete_keyframes(selected_fields, selected_keyframes); } void KeyframeView::set_x_scroll(int s) { @@ -201,6 +186,8 @@ void KeyframeView::resize_move(double d) { void KeyframeView::mousePressEvent(QMouseEvent *event) { rect_select_x = event->x(); rect_select_y = event->y(); + rect_select_w = 0; + rect_select_h = 0; if (panel_timeline->tool == TIMELINE_TOOL_HAND || event->buttons() & Qt::MiddleButton) { scroll_drag = true; @@ -244,7 +231,11 @@ void KeyframeView::mousePressEvent(QMouseEvent *event) { } bool already_selected = false; keys_selected = false; - if (keyframe_index > -1) already_selected = keyframeIsSelected(rows.at(row_index)->field(field_index), keyframe_index); + if (keyframe_index > -1) { + already_selected = keyframeIsSelected(rows.at(row_index)->field(field_index), keyframe_index); + } else { + select_rect = true; + } if (!already_selected) { if (!(event->modifiers() & Qt::ShiftModifier)) { selected_fields.clear(); @@ -274,10 +265,11 @@ void KeyframeView::mousePressEvent(QMouseEvent *event) { for (int i=0;ikeyframes.at(selected_keyframes.at(i)).time); } - keys_selected = true; } + rect_select_offset = selected_fields.size(); + update_keys(); if (event->button() == Qt::LeftButton) { @@ -298,7 +290,40 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) { rect_select_y = event->pos().y(); } else if (mousedown) { int mouse_x = event->x() + x_scroll; - if (keys_selected) { + if (select_rect) { + // do a rect select + selected_fields.resize(rect_select_offset); + selected_keyframes.resize(rect_select_offset); + + rect_select_w = event->x() - rect_select_x; + rect_select_h = event->y() - rect_select_y; + + int min_row = qMin(rect_select_y, event->y())-KEYFRAME_SIZE; + int max_row = qMax(rect_select_y, event->y())+KEYFRAME_SIZE; + + long frame_start = getFrameFromScreenPoint(panel_effect_controls->zoom, rect_select_x+x_scroll); + long frame_end = getFrameFromScreenPoint(panel_effect_controls->zoom, mouse_x); + long min_frame = qMin(frame_start, frame_end)-KEYFRAME_SIZE; + long max_frame = qMax(frame_start, frame_end)+KEYFRAME_SIZE; + + for (int i=0;i= min_row && rowY.at(i) <= max_row) { + EffectRow* row = rows.at(i); + for (int k=0;kfieldCount();k++) { + EffectField* field = row->field(k); + for (int j=0;jkeyframes.size();j++) { + long keyframe_frame = adjust_row_keyframe(row, field->keyframes.at(j).time); + if (!keyframeIsSelected(field, j) && keyframe_frame >= min_frame && keyframe_frame <= max_frame) { + selected_fields.append(field); + selected_keyframes.append(j); + } + } + } + } + } + + update_keys(); + } else if (keys_selected) { // move keyframes long frame_diff = getFrameFromScreenPoint(panel_effect_controls->zoom, mouse_x) - drag_frame_start; @@ -345,38 +370,6 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) { dragging = true; update_ui(false); - } else { - // do a rect select - rect_select_w = event->x() - rect_select_x; - rect_select_h = event->y() - rect_select_y; - - int min_row = qMin(rect_select_y, event->y())-KEYFRAME_SIZE; - int max_row = qMax(rect_select_y, event->y())+KEYFRAME_SIZE; - - long frame_start = getFrameFromScreenPoint(panel_effect_controls->zoom, rect_select_x+x_scroll); - long frame_end = getFrameFromScreenPoint(panel_effect_controls->zoom, mouse_x); - long min_frame = qMin(frame_start, frame_end)-KEYFRAME_SIZE; - long max_frame = qMax(frame_start, frame_end)+KEYFRAME_SIZE; - - for (int i=0;i= min_row && rowY.at(i) <= max_row) { - EffectRow* row = rows.at(i); - for (int k=0;kfieldCount();k++) { - EffectField* field = row->field(k); - for (int j=0;jkeyframes.size();j++) { - long keyframe_frame = adjust_row_keyframe(row, field->keyframes.at(j).time); - if (!keyframeIsSelected(field, j) && keyframe_frame >= min_frame && keyframe_frame <= max_frame) { - selected_fields.append(field); - selected_keyframes.append(j); - } - } - } - } - } - - select_rect = true; - - update_keys(); } } } diff --git a/ui/keyframeview.h b/ui/keyframeview.h index 59a328ed9..51bbd361d 100644 --- a/ui/keyframeview.h +++ b/ui/keyframeview.h @@ -27,7 +27,7 @@ public slots: void resize_move(double d); private: long adjust_row_keyframe(EffectRow* row, long time); - QVector selected_fields; + QVector selected_fields; QVector selected_keyframes; QVector rowY; QVector rows; @@ -42,7 +42,7 @@ private: bool select_rect; bool scroll_drag; - bool keyframeIsSelected(EffectField *field, int keyframe); + bool keyframeIsSelected(EffectField *field, int keyframe); long drag_frame_start; long last_frame_diff; @@ -50,6 +50,7 @@ private: int rect_select_y; int rect_select_w; int rect_select_h; + int rect_select_offset; int x_scroll; int y_scroll;