diff --git a/io/config.cpp b/io/config.cpp index 133dad50a..d4cbac676 100644 --- a/io/config.cpp +++ b/io/config.cpp @@ -33,258 +33,258 @@ Config olive::CurrentConfig; RuntimeConfig olive::CurrentRuntimeConfig; Config::Config() - : saved_layout(false), - show_track_lines(true), - scroll_zooms(false), - edit_tool_selects_links(false), - edit_tool_also_seeks(false), - select_also_seeks(false), - paste_seeks(true), - img_seq_formats("jpg|jpeg|bmp|tiff|tif|psd|png|tga|jp2|gif"), - rectified_waveforms(false), - default_transition_length(30), - timecode_view(TIMECODE_DROP), - show_title_safe_area(false), - use_custom_title_safe_ratio(false), - custom_title_safe_ratio(1), - enable_drag_files_to_timeline(true), - autoscale_by_default(false), - recording_mode(2), - enable_seek_to_import(false), - enable_audio_scrubbing(true), - drop_on_media_to_replace(true), - autoscroll(AUTOSCROLL_PAGE_SCROLL), - audio_rate(48000), - fast_seeking(false), - hover_focus(false), - project_view_type(PROJECT_VIEW_TREE), - set_name_with_marker(true), - show_project_toolbar(false), - previous_queue_size(3), - previous_queue_type(FRAME_QUEUE_TYPE_FRAMES), - upcoming_queue_size(0.5), - upcoming_queue_type(FRAME_QUEUE_TYPE_SECONDS), - loop(false), - seek_also_selects(false), - effect_textbox_lines(3), - use_software_fallback(false), - center_timeline_timecodes(true), - waveform_resolution(64), - thumbnail_resolution(120), - add_default_effects_to_clips(true) + : saved_layout(false), + show_track_lines(true), + scroll_zooms(false), + edit_tool_selects_links(false), + edit_tool_also_seeks(false), + select_also_seeks(false), + paste_seeks(true), + img_seq_formats("jpg|jpeg|bmp|tiff|tif|psd|png|tga|jp2|gif"), + rectified_waveforms(false), + default_transition_length(30), + timecode_view(TIMECODE_DROP), + show_title_safe_area(false), + use_custom_title_safe_ratio(false), + custom_title_safe_ratio(1), + enable_drag_files_to_timeline(true), + autoscale_by_default(false), + recording_mode(2), + enable_seek_to_import(false), + enable_audio_scrubbing(true), + drop_on_media_to_replace(true), + autoscroll(AUTOSCROLL_PAGE_SCROLL), + audio_rate(48000), + fast_seeking(false), + hover_focus(false), + project_view_type(PROJECT_VIEW_TREE), + set_name_with_marker(true), + show_project_toolbar(false), + previous_queue_size(3), + previous_queue_type(FRAME_QUEUE_TYPE_FRAMES), + upcoming_queue_size(0.5), + upcoming_queue_type(FRAME_QUEUE_TYPE_SECONDS), + loop(false), + seek_also_selects(false), + effect_textbox_lines(3), + use_software_fallback(false), + center_timeline_timecodes(true), + waveform_resolution(64), + thumbnail_resolution(120), + add_default_effects_to_clips(true) {} void Config::load(QString path) { - QFile f(path); - if (f.exists() && f.open(QIODevice::ReadOnly)) { - QXmlStreamReader stream(&f); + QFile f(path); + if (f.exists() && f.open(QIODevice::ReadOnly)) { + QXmlStreamReader stream(&f); - while (!stream.atEnd()) { - stream.readNext(); - if (stream.isStartElement()) { - if (stream.name() == "SavedLayout") { - stream.readNext(); - saved_layout = (stream.text() == "1"); - } else if (stream.name() == "ShowTrackLines") { - stream.readNext(); - show_track_lines = (stream.text() == "1"); - } else if (stream.name() == "ScrollZooms") { - stream.readNext(); - scroll_zooms = (stream.text() == "1"); - } else if (stream.name() == "EditToolSelectsLinks") { - stream.readNext(); - edit_tool_selects_links = (stream.text() == "1"); - } else if (stream.name() == "EditToolAlsoSeeks") { - stream.readNext(); - edit_tool_also_seeks = (stream.text() == "1"); - } else if (stream.name() == "SelectAlsoSeeks") { - stream.readNext(); - select_also_seeks = (stream.text() == "1"); - } else if (stream.name() == "PasteSeeks") { - stream.readNext(); - paste_seeks = (stream.text() == "1"); - } else if (stream.name() == "ImageSequenceFormats") { - stream.readNext(); - img_seq_formats = stream.text().toString(); - } else if (stream.name() == "RectifiedWaveforms") { - stream.readNext(); - rectified_waveforms = (stream.text() == "1"); - } else if (stream.name() == "DefaultTransitionLength") { - stream.readNext(); - default_transition_length = stream.text().toInt(); - } else if (stream.name() == "TimecodeView") { - stream.readNext(); - timecode_view = stream.text().toInt(); - } else if (stream.name() == "ShowTitleSafeArea") { - stream.readNext(); - show_title_safe_area = (stream.text() == "1"); - } else if (stream.name() == "UseCustomTitleSafeRatio") { - stream.readNext(); - use_custom_title_safe_ratio = (stream.text() == "1"); - } else if (stream.name() == "CustomTitleSafeRatio") { - stream.readNext(); - custom_title_safe_ratio = stream.text().toDouble(); - } else if (stream.name() == "EnableDragFilesToTimeline") { - stream.readNext(); - enable_drag_files_to_timeline = (stream.text() == "1");; - } else if (stream.name() == "AutoscaleByDefault") { - stream.readNext(); - autoscale_by_default = (stream.text() == "1"); - } else if (stream.name() == "RecordingMode") { - stream.readNext(); - recording_mode = stream.text().toInt(); - } else if (stream.name() == "EnableSeekToImport") { - stream.readNext(); - enable_seek_to_import = (stream.text() == "1"); - } else if (stream.name() == "AudioScrubbing") { - stream.readNext(); - enable_audio_scrubbing = (stream.text() == "1"); - } else if (stream.name() == "DropFileOnMediaToReplace") { - stream.readNext(); - drop_on_media_to_replace = (stream.text() == "1"); - } else if (stream.name() == "Autoscroll") { - stream.readNext(); - autoscroll = stream.text().toInt(); - } else if (stream.name() == "AudioRate") { - stream.readNext(); - audio_rate = stream.text().toInt(); - } else if (stream.name() == "FastSeeking") { - stream.readNext(); - fast_seeking = (stream.text() == "1"); - } else if (stream.name() == "HoverFocus") { - stream.readNext(); - hover_focus = (stream.text() == "1"); - } else if (stream.name() == "ProjectViewType") { - stream.readNext(); - project_view_type = stream.text().toInt(); - } else if (stream.name() == "SetNameWithMarker") { - stream.readNext(); - set_name_with_marker = (stream.text() == "1"); - } else if (stream.name() == "ShowProjectToolbar") { - stream.readNext(); - show_project_toolbar = (stream.text() == "1"); - } else if (stream.name() == "PreviousFrameQueueSize") { - stream.readNext(); - previous_queue_size = stream.text().toDouble(); - } else if (stream.name() == "PreviousFrameQueueType") { - stream.readNext(); - previous_queue_type = stream.text().toInt(); - } else if (stream.name() == "UpcomingFrameQueueSize") { - stream.readNext(); - upcoming_queue_size = stream.text().toDouble(); - } else if (stream.name() == "UpcomingFrameQueueType") { - stream.readNext(); - upcoming_queue_type = stream.text().toInt(); - } else if (stream.name() == "Loop") { - stream.readNext(); - loop = (stream.text() == "1"); - } else if (stream.name() == "SeekAlsoSelects") { - stream.readNext(); - seek_also_selects = (stream.text() == "1"); - } else if (stream.name() == "CSSPath") { - stream.readNext(); - css_path = stream.text().toString(); - } else if (stream.name() == "EffectTextboxLines") { - stream.readNext(); - effect_textbox_lines = stream.text().toInt(); - } else if (stream.name() == "UseSoftwareFallback") { - stream.readNext(); - use_software_fallback = (stream.text() == "1"); - } else if (stream.name() == "CenterTimelineTimecodes") { - stream.readNext(); - center_timeline_timecodes = (stream.text() == "1"); - } else if (stream.name() == "PreferredAudioOutput") { - stream.readNext(); - preferred_audio_output = stream.text().toString(); - } else if (stream.name() == "PreferredAudioInput") { - stream.readNext(); - preferred_audio_input = stream.text().toString(); - } else if (stream.name() == "LanguageFile") { - stream.readNext(); - language_file = stream.text().toString(); - } else if (stream.name() == "ThumbnailResolution") { - stream.readNext(); - thumbnail_resolution = stream.text().toInt(); - } else if (stream.name() == "WaveformResolution") { - stream.readNext(); - waveform_resolution = stream.text().toInt(); - } else if (stream.name() == "AddDefaultEffectsToClips") { - stream.readNext(); - add_default_effects_to_clips = (stream.text() == "1"); - } - } - } - if (stream.hasError()) { - qCritical() << "Error parsing config XML." << stream.errorString(); - } + while (!stream.atEnd()) { + stream.readNext(); + if (stream.isStartElement()) { + if (stream.name() == "SavedLayout") { + stream.readNext(); + saved_layout = (stream.text() == "1"); + } else if (stream.name() == "ShowTrackLines") { + stream.readNext(); + show_track_lines = (stream.text() == "1"); + } else if (stream.name() == "ScrollZooms") { + stream.readNext(); + scroll_zooms = (stream.text() == "1"); + } else if (stream.name() == "EditToolSelectsLinks") { + stream.readNext(); + edit_tool_selects_links = (stream.text() == "1"); + } else if (stream.name() == "EditToolAlsoSeeks") { + stream.readNext(); + edit_tool_also_seeks = (stream.text() == "1"); + } else if (stream.name() == "SelectAlsoSeeks") { + stream.readNext(); + select_also_seeks = (stream.text() == "1"); + } else if (stream.name() == "PasteSeeks") { + stream.readNext(); + paste_seeks = (stream.text() == "1"); + } else if (stream.name() == "ImageSequenceFormats") { + stream.readNext(); + img_seq_formats = stream.text().toString(); + } else if (stream.name() == "RectifiedWaveforms") { + stream.readNext(); + rectified_waveforms = (stream.text() == "1"); + } else if (stream.name() == "DefaultTransitionLength") { + stream.readNext(); + default_transition_length = stream.text().toInt(); + } else if (stream.name() == "TimecodeView") { + stream.readNext(); + timecode_view = stream.text().toInt(); + } else if (stream.name() == "ShowTitleSafeArea") { + stream.readNext(); + show_title_safe_area = (stream.text() == "1"); + } else if (stream.name() == "UseCustomTitleSafeRatio") { + stream.readNext(); + use_custom_title_safe_ratio = (stream.text() == "1"); + } else if (stream.name() == "CustomTitleSafeRatio") { + stream.readNext(); + custom_title_safe_ratio = stream.text().toDouble(); + } else if (stream.name() == "EnableDragFilesToTimeline") { + stream.readNext(); + enable_drag_files_to_timeline = (stream.text() == "1");; + } else if (stream.name() == "AutoscaleByDefault") { + stream.readNext(); + autoscale_by_default = (stream.text() == "1"); + } else if (stream.name() == "RecordingMode") { + stream.readNext(); + recording_mode = stream.text().toInt(); + } else if (stream.name() == "EnableSeekToImport") { + stream.readNext(); + enable_seek_to_import = (stream.text() == "1"); + } else if (stream.name() == "AudioScrubbing") { + stream.readNext(); + enable_audio_scrubbing = (stream.text() == "1"); + } else if (stream.name() == "DropFileOnMediaToReplace") { + stream.readNext(); + drop_on_media_to_replace = (stream.text() == "1"); + } else if (stream.name() == "Autoscroll") { + stream.readNext(); + autoscroll = stream.text().toInt(); + } else if (stream.name() == "AudioRate") { + stream.readNext(); + audio_rate = stream.text().toInt(); + } else if (stream.name() == "FastSeeking") { + stream.readNext(); + fast_seeking = (stream.text() == "1"); + } else if (stream.name() == "HoverFocus") { + stream.readNext(); + hover_focus = (stream.text() == "1"); + } else if (stream.name() == "ProjectViewType") { + stream.readNext(); + project_view_type = stream.text().toInt(); + } else if (stream.name() == "SetNameWithMarker") { + stream.readNext(); + set_name_with_marker = (stream.text() == "1"); + } else if (stream.name() == "ShowProjectToolbar") { + stream.readNext(); + show_project_toolbar = (stream.text() == "1"); + } else if (stream.name() == "PreviousFrameQueueSize") { + stream.readNext(); + previous_queue_size = stream.text().toDouble(); + } else if (stream.name() == "PreviousFrameQueueType") { + stream.readNext(); + previous_queue_type = stream.text().toInt(); + } else if (stream.name() == "UpcomingFrameQueueSize") { + stream.readNext(); + upcoming_queue_size = stream.text().toDouble(); + } else if (stream.name() == "UpcomingFrameQueueType") { + stream.readNext(); + upcoming_queue_type = stream.text().toInt(); + } else if (stream.name() == "Loop") { + stream.readNext(); + loop = (stream.text() == "1"); + } else if (stream.name() == "SeekAlsoSelects") { + stream.readNext(); + seek_also_selects = (stream.text() == "1"); + } else if (stream.name() == "CSSPath") { + stream.readNext(); + css_path = stream.text().toString(); + } else if (stream.name() == "EffectTextboxLines") { + stream.readNext(); + effect_textbox_lines = stream.text().toInt(); + } else if (stream.name() == "UseSoftwareFallback") { + stream.readNext(); + use_software_fallback = (stream.text() == "1"); + } else if (stream.name() == "CenterTimelineTimecodes") { + stream.readNext(); + center_timeline_timecodes = (stream.text() == "1"); + } else if (stream.name() == "PreferredAudioOutput") { + stream.readNext(); + preferred_audio_output = stream.text().toString(); + } else if (stream.name() == "PreferredAudioInput") { + stream.readNext(); + preferred_audio_input = stream.text().toString(); + } else if (stream.name() == "LanguageFile") { + stream.readNext(); + language_file = stream.text().toString(); + } else if (stream.name() == "ThumbnailResolution") { + stream.readNext(); + thumbnail_resolution = stream.text().toInt(); + } else if (stream.name() == "WaveformResolution") { + stream.readNext(); + waveform_resolution = stream.text().toInt(); + } else if (stream.name() == "AddDefaultEffectsToClips") { + stream.readNext(); + add_default_effects_to_clips = (stream.text() == "1"); + } + } + } + if (stream.hasError()) { + qCritical() << "Error parsing config XML." << stream.errorString(); + } - f.close(); - } + f.close(); + } } void Config::save(QString path) { - QFile f(path); - if (!f.open(QIODevice::WriteOnly)) { - qCritical() << "Could not save configuration"; - return; - } + QFile f(path); + if (!f.open(QIODevice::WriteOnly)) { + qCritical() << "Could not save configuration"; + return; + } - QXmlStreamWriter stream(&f); - stream.setAutoFormatting(true); - stream.writeStartDocument(); // doc - stream.writeStartElement("Configuration"); // configuration + QXmlStreamWriter stream(&f); + stream.setAutoFormatting(true); + stream.writeStartDocument(); // doc + stream.writeStartElement("Configuration"); // configuration - stream.writeTextElement("Version", QString::number(SAVE_VERSION)); - stream.writeTextElement("SavedLayout", QString::number(saved_layout)); - stream.writeTextElement("ShowTrackLines", QString::number(show_track_lines)); - stream.writeTextElement("ScrollZooms", QString::number(scroll_zooms)); - stream.writeTextElement("EditToolSelectsLinks", QString::number(edit_tool_selects_links)); - stream.writeTextElement("EditToolAlsoSeeks", QString::number(edit_tool_also_seeks)); - stream.writeTextElement("SelectAlsoSeeks", QString::number(select_also_seeks)); - stream.writeTextElement("PasteSeeks", QString::number(paste_seeks)); - stream.writeTextElement("ImageSequenceFormats", img_seq_formats); - stream.writeTextElement("RectifiedWaveforms", QString::number(rectified_waveforms)); - stream.writeTextElement("DefaultTransitionLength", QString::number(default_transition_length)); - stream.writeTextElement("TimecodeView", QString::number(timecode_view)); - stream.writeTextElement("ShowTitleSafeArea", QString::number(show_title_safe_area)); - stream.writeTextElement("UseCustomTitleSafeRatio", QString::number(use_custom_title_safe_ratio)); - stream.writeTextElement("CustomTitleSafeRatio", QString::number(custom_title_safe_ratio)); - stream.writeTextElement("EnableDragFilesToTimeline", QString::number(enable_drag_files_to_timeline)); - stream.writeTextElement("AutoscaleByDefault", QString::number(autoscale_by_default)); - stream.writeTextElement("RecordingMode", QString::number(recording_mode)); - stream.writeTextElement("EnableSeekToImport", QString::number(enable_seek_to_import)); - stream.writeTextElement("AudioScrubbing", QString::number(enable_audio_scrubbing)); - stream.writeTextElement("DropFileOnMediaToReplace", QString::number(drop_on_media_to_replace)); - stream.writeTextElement("Autoscroll", QString::number(autoscroll)); - stream.writeTextElement("AudioRate", QString::number(audio_rate)); - stream.writeTextElement("FastSeeking", QString::number(fast_seeking)); - stream.writeTextElement("HoverFocus", QString::number(hover_focus)); - stream.writeTextElement("ProjectViewType", QString::number(project_view_type)); - stream.writeTextElement("SetNameWithMarker", QString::number(set_name_with_marker)); - stream.writeTextElement("ShowProjectToolbar", QString::number(panel_project->toolbar_widget->isVisible())); - stream.writeTextElement("PreviousFrameQueueSize", QString::number(previous_queue_size)); - stream.writeTextElement("PreviousFrameQueueType", QString::number(previous_queue_type)); - stream.writeTextElement("UpcomingFrameQueueSize", QString::number(upcoming_queue_size)); - stream.writeTextElement("UpcomingFrameQueueType", QString::number(upcoming_queue_type)); - stream.writeTextElement("Loop", QString::number(loop)); - stream.writeTextElement("SeekAlsoSelects", QString::number(seek_also_selects)); - stream.writeTextElement("CSSPath", css_path); - stream.writeTextElement("EffectTextboxLines", QString::number(effect_textbox_lines)); - stream.writeTextElement("UseSoftwareFallback", QString::number(use_software_fallback)); - stream.writeTextElement("CenterTimelineTimecodes", QString::number(center_timeline_timecodes)); - stream.writeTextElement("PreferredAudioOutput", preferred_audio_output); - stream.writeTextElement("PreferredAudioInput", preferred_audio_input); - stream.writeTextElement("LanguageFile", language_file); - stream.writeTextElement("ThumbnailResolution", QString::number(thumbnail_resolution)); - stream.writeTextElement("WaveformResolution", QString::number(waveform_resolution)); - stream.writeTextElement("AddDefaultEffectsToClips", QString::number(add_default_effects_to_clips)); + stream.writeTextElement("Version", QString::number(SAVE_VERSION)); + stream.writeTextElement("SavedLayout", QString::number(saved_layout)); + stream.writeTextElement("ShowTrackLines", QString::number(show_track_lines)); + stream.writeTextElement("ScrollZooms", QString::number(scroll_zooms)); + stream.writeTextElement("EditToolSelectsLinks", QString::number(edit_tool_selects_links)); + stream.writeTextElement("EditToolAlsoSeeks", QString::number(edit_tool_also_seeks)); + stream.writeTextElement("SelectAlsoSeeks", QString::number(select_also_seeks)); + stream.writeTextElement("PasteSeeks", QString::number(paste_seeks)); + stream.writeTextElement("ImageSequenceFormats", img_seq_formats); + stream.writeTextElement("RectifiedWaveforms", QString::number(rectified_waveforms)); + stream.writeTextElement("DefaultTransitionLength", QString::number(default_transition_length)); + stream.writeTextElement("TimecodeView", QString::number(timecode_view)); + stream.writeTextElement("ShowTitleSafeArea", QString::number(show_title_safe_area)); + stream.writeTextElement("UseCustomTitleSafeRatio", QString::number(use_custom_title_safe_ratio)); + stream.writeTextElement("CustomTitleSafeRatio", QString::number(custom_title_safe_ratio)); + stream.writeTextElement("EnableDragFilesToTimeline", QString::number(enable_drag_files_to_timeline)); + stream.writeTextElement("AutoscaleByDefault", QString::number(autoscale_by_default)); + stream.writeTextElement("RecordingMode", QString::number(recording_mode)); + stream.writeTextElement("EnableSeekToImport", QString::number(enable_seek_to_import)); + stream.writeTextElement("AudioScrubbing", QString::number(enable_audio_scrubbing)); + stream.writeTextElement("DropFileOnMediaToReplace", QString::number(drop_on_media_to_replace)); + stream.writeTextElement("Autoscroll", QString::number(autoscroll)); + stream.writeTextElement("AudioRate", QString::number(audio_rate)); + stream.writeTextElement("FastSeeking", QString::number(fast_seeking)); + stream.writeTextElement("HoverFocus", QString::number(hover_focus)); + stream.writeTextElement("ProjectViewType", QString::number(project_view_type)); + stream.writeTextElement("SetNameWithMarker", QString::number(set_name_with_marker)); + stream.writeTextElement("ShowProjectToolbar", QString::number(panel_project->toolbar_widget->isVisible())); + stream.writeTextElement("PreviousFrameQueueSize", QString::number(previous_queue_size)); + stream.writeTextElement("PreviousFrameQueueType", QString::number(previous_queue_type)); + stream.writeTextElement("UpcomingFrameQueueSize", QString::number(upcoming_queue_size)); + stream.writeTextElement("UpcomingFrameQueueType", QString::number(upcoming_queue_type)); + stream.writeTextElement("Loop", QString::number(loop)); + stream.writeTextElement("SeekAlsoSelects", QString::number(seek_also_selects)); + stream.writeTextElement("CSSPath", css_path); + stream.writeTextElement("EffectTextboxLines", QString::number(effect_textbox_lines)); + stream.writeTextElement("UseSoftwareFallback", QString::number(use_software_fallback)); + stream.writeTextElement("CenterTimelineTimecodes", QString::number(center_timeline_timecodes)); + stream.writeTextElement("PreferredAudioOutput", preferred_audio_output); + stream.writeTextElement("PreferredAudioInput", preferred_audio_input); + stream.writeTextElement("LanguageFile", language_file); + stream.writeTextElement("ThumbnailResolution", QString::number(thumbnail_resolution)); + stream.writeTextElement("WaveformResolution", QString::number(waveform_resolution)); + stream.writeTextElement("AddDefaultEffectsToClips", QString::number(add_default_effects_to_clips)); - stream.writeEndElement(); // configuration - stream.writeEndDocument(); // doc - f.close(); + stream.writeEndElement(); // configuration + stream.writeEndDocument(); // doc + f.close(); } RuntimeConfig::RuntimeConfig() : - shaders_are_enabled(true), - disable_blending(false) + shaders_are_enabled(true), + disable_blending(false) {} diff --git a/io/config.h b/io/config.h index 23a6a86b9..8b907779a 100644 --- a/io/config.h +++ b/io/config.h @@ -45,67 +45,67 @@ #define FRAME_QUEUE_TYPE_SECONDS 1 struct Config { - Config(); + Config(); - bool saved_layout; - bool show_track_lines; - bool scroll_zooms; - bool edit_tool_selects_links; - bool edit_tool_also_seeks; - bool select_also_seeks; - bool paste_seeks; - QString img_seq_formats; - bool rectified_waveforms; - int default_transition_length; - int timecode_view; - bool show_title_safe_area; - bool use_custom_title_safe_ratio; - double custom_title_safe_ratio; - bool enable_drag_files_to_timeline; - bool autoscale_by_default; - int recording_mode; - bool enable_seek_to_import; - bool enable_audio_scrubbing; - bool drop_on_media_to_replace; - int autoscroll; - int audio_rate; - bool fast_seeking; - bool hover_focus; - int project_view_type; - bool set_name_with_marker; - bool show_project_toolbar; - double previous_queue_size; - int previous_queue_type; - double upcoming_queue_size; - int upcoming_queue_type; - bool loop; - bool seek_also_selects; - QString css_path; - int effect_textbox_lines; - bool use_software_fallback; - bool center_timeline_timecodes; - QString preferred_audio_output; - QString preferred_audio_input; - QString language_file; - int waveform_resolution; - int thumbnail_resolution; - bool add_default_effects_to_clips; + bool saved_layout; + bool show_track_lines; + bool scroll_zooms; + bool edit_tool_selects_links; + bool edit_tool_also_seeks; + bool select_also_seeks; + bool paste_seeks; + QString img_seq_formats; + bool rectified_waveforms; + int default_transition_length; + int timecode_view; + bool show_title_safe_area; + bool use_custom_title_safe_ratio; + double custom_title_safe_ratio; + bool enable_drag_files_to_timeline; + bool autoscale_by_default; + int recording_mode; + bool enable_seek_to_import; + bool enable_audio_scrubbing; + bool drop_on_media_to_replace; + int autoscroll; + int audio_rate; + bool fast_seeking; + bool hover_focus; + int project_view_type; + bool set_name_with_marker; + bool show_project_toolbar; + double previous_queue_size; + int previous_queue_type; + double upcoming_queue_size; + int upcoming_queue_type; + bool loop; + bool seek_also_selects; + QString css_path; + int effect_textbox_lines; + bool use_software_fallback; + bool center_timeline_timecodes; + QString preferred_audio_output; + QString preferred_audio_input; + QString language_file; + int waveform_resolution; + int thumbnail_resolution; + bool add_default_effects_to_clips; - void load(QString path); - void save(QString path); + void load(QString path); + void save(QString path); }; struct RuntimeConfig { - RuntimeConfig(); + RuntimeConfig(); - bool shaders_are_enabled; - bool disable_blending; - QString external_translation_file; + bool shaders_are_enabled; + bool disable_blending; + QString external_translation_file; }; namespace olive { - extern Config CurrentConfig; - extern RuntimeConfig CurrentRuntimeConfig; +extern Config CurrentConfig; +extern RuntimeConfig CurrentRuntimeConfig; } #endif // CONFIG_H diff --git a/mainwindow.cpp b/mainwindow.cpp index 169b9d087..1ee7b1b72 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -426,8 +426,8 @@ void MainWindow::setup_menus() { view_menu->addAction(tr("Zoom In"), &olive::FocusFilter, SLOT(zoom_in()), QKeySequence("="))->setProperty("id", "zoomin"); view_menu->addAction(tr("Zoom Out"), &olive::FocusFilter, SLOT(zoom_out()), QKeySequence("-"))->setProperty("id", "zoomout"); - view_menu->addAction(tr("Increase Track Height"), panel_timeline, SLOT(increase_track_height()), QKeySequence("Ctrl+="))->setProperty("id", "vzoomin"); - view_menu->addAction(tr("Decrease Track Height"), panel_timeline, SLOT(decrease_track_height()), QKeySequence("Ctrl+-"))->setProperty("id", "vzoomout"); + view_menu->addAction(tr("Increase Track Height"), panel_timeline, SLOT(IncreaseTrackHeight()), QKeySequence("Ctrl+="))->setProperty("id", "vzoomin"); + view_menu->addAction(tr("Decrease Track Height"), panel_timeline, SLOT(DecreaseTrackHeight()), QKeySequence("Ctrl+-"))->setProperty("id", "vzoomout"); show_all = view_menu->addAction(tr("Toggle Show All"), panel_timeline, SLOT(toggle_show_all()), QKeySequence("\\")); show_all->setProperty("id", "showall"); diff --git a/panels/grapheditor.cpp b/panels/grapheditor.cpp index bf8e0148d..f8f4d53e1 100644 --- a/panels/grapheditor.cpp +++ b/panels/grapheditor.cpp @@ -38,8 +38,6 @@ #include "debug.h" GraphEditor::GraphEditor(QWidget* parent) : Panel(parent), row(nullptr) { - setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - resize(720, 480); QWidget* main_widget = new QWidget(this); diff --git a/panels/project.cpp b/panels/project.cpp index 58d1b6324..df4dc0d3c 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -72,8 +72,6 @@ QStringList recent_projects; Project::Project(QWidget *parent) : Panel(parent) { - setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - QWidget* dockWidgetContents = new QWidget(this); QVBoxLayout* verticalLayout = new QVBoxLayout(dockWidgetContents); diff --git a/panels/timeline.cpp b/panels/timeline.cpp index 4f3ae7e72..6488f94b3 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -71,7 +71,7 @@ Timeline::Timeline(QWidget *parent) : moving_proc(false), move_insert(false), trim_target(-1), - trim_in_point(false), + trim_type(TRIM_NONE), splitting(false), importing(false), importing_files(false), @@ -84,12 +84,8 @@ Timeline::Timeline(QWidget *parent) : block_repaints(false), scroll(0) { - setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - setup_ui(); - default_track_height = qRound((QGuiApplication::primaryScreen()->logicalDotsPerInch() / 96) * TRACK_DEFAULT_HEIGHT); - headers->viewer = panel_sequence_viewer; video_area->bottom_align = true; @@ -233,7 +229,7 @@ void Timeline::create_ghosts_from_media(SequencePtr seq, long entry_point, QVect if (can_import) { Ghost g; g.clip = -1; - g.trimming = false; + g.trim_type = TRIM_NONE; g.old_clip_in = g.clip_in = default_clip_in; g.media = medium; g.in = entry_point; @@ -374,14 +370,6 @@ void Timeline::add_clips_from_ghosts(ComboAction* ca, SequencePtr s) { snapped = false; } -int Timeline::get_track_height_size(bool video) { - if (video) { - return video_track_heights.size(); - } else { - return audio_track_heights.size(); - } -} - void Timeline::add_transition() { ComboAction* ca = new ComboAction(); bool adding = false; @@ -472,18 +460,6 @@ void Timeline::nest() { } } -int Timeline::calculate_track_height(int track, int value) { - int index = (track < 0) ? qAbs(track + 1) : track; - QVector& vector = (track < 0) ? video_track_heights : audio_track_heights; - while (vector.size() < index+1) { - vector.append(default_track_height); - } - if (value > -1) { - vector[index] = value; - } - return vector.at(index); -} - void Timeline::update_sequence() { bool null_sequence = (olive::ActiveSequence == nullptr); @@ -793,15 +769,6 @@ void Timeline::decheck_tool_buttons(QObject* sender) { } } -QVector Timeline::get_tracks_of_linked_clips(int i) { - QVector tracks; - ClipPtr clip = olive::ActiveSequence->clips.at(i); - for (int j=0;jlinked.size();j++) { - tracks.append(olive::ActiveSequence->clips.at(clip->linked.at(j))->track); - } - return tracks; -} - void Timeline::zoom_in() { multiply_zoom(2.0); } @@ -810,6 +777,45 @@ void Timeline::zoom_out() { multiply_zoom(0.5); } +int Timeline::GetTrackHeight(int track) { + for (int i=0;isequence->selections.size();i++) { const Selection& s = clip->sequence->selections.at(i); @@ -886,18 +892,9 @@ ClipPtr Timeline::split_clip(ComboAction* ca, bool transitions, int p, long fram return nullptr; } -bool Timeline::has_clip_been_split(int c) { - for (int i=0;ilinked.size();i++) { int l = c->linked.at(i); - if (!has_clip_been_split(l)) { + if (!split_cache.contains(l)) { ClipPtr link = olive::ActiveSequence->clips.at(l); if ((original_clip_is_selected && is_clip_selected(link, true)) || !original_clip_is_selected) { split_cache.append(l); @@ -1675,32 +1672,6 @@ void Timeline::toggle_links() { } } -void Timeline::increase_track_height() { - for (int i=0;iselections.clear(); repaint_timeline(); diff --git a/panels/timeline.h b/panels/timeline.h index ac7d2033c..9376d089b 100644 --- a/panels/timeline.h +++ b/panels/timeline.h @@ -35,14 +35,20 @@ #include "ui/audiomonitor.h" #include "ui/panel.h" -#define TRACK_DEFAULT_HEIGHT 40 +enum CreateObjects { + ADD_OBJ_TITLE, + ADD_OBJ_SOLID, + ADD_OBJ_BARS, + ADD_OBJ_TONE, + ADD_OBJ_NOISE, + ADD_OBJ_AUDIO +}; -#define ADD_OBJ_TITLE 0 -#define ADD_OBJ_SOLID 1 -#define ADD_OBJ_BARS 2 -#define ADD_OBJ_TONE 3 -#define ADD_OBJ_NOISE 4 -#define ADD_OBJ_AUDIO 5 +enum TrimType { + TRIM_NONE, + TRIM_IN, + TRIM_OUT +}; bool is_clip_selected(ClipPtr clip, bool containing); int getScreenPointFromFrame(double zoom, long frame); @@ -70,8 +76,7 @@ struct Ghost { // other variables long ghost_length; long media_length; - bool trim_in; - bool trimming; + TrimType trim_type; // transition trimming TransitionPtr transition; @@ -82,7 +87,7 @@ class Timeline : public Panel Q_OBJECT public: explicit Timeline(QWidget *parent = nullptr); - ~Timeline(); + virtual ~Timeline() override; bool focused(); void multiply_zoom(double m); @@ -98,8 +103,6 @@ public: void relink_clips_using_ids(QVector& old_clips, QVector& new_clips); void update_sequence(); - QVector get_tracks_of_linked_clips(int i); - bool has_clip_been_split(int c); void edit_to_point_internal(bool in, bool ripple); void delete_in_out_internal(bool ripple); @@ -128,10 +131,8 @@ public: bool showing_all; double old_zoom; - QVector video_track_heights; - QVector audio_track_heights; - int get_track_height_size(bool video); - int calculate_track_height(int track, int height); + int GetTrackHeight(int track); + void SetTrackHeight(int track, int height); // snapping bool snapping; @@ -145,10 +146,7 @@ public: void select_all(); bool rect_select_init; bool rect_select_proc; - int rect_select_x; - int rect_select_y; - int rect_select_w; - int rect_select_h; + QRect rect_select_rect; // moving bool moving_init; @@ -160,7 +158,7 @@ public: // trimming int trim_target; - bool trim_in_point; + TrimType trim_type; int transition_select; // splitting @@ -211,8 +209,8 @@ public: bool can_ripple_empty_space(long frame, int track); - void resizeEvent(QResizeEvent *event); protected: + virtual void resizeEvent(QResizeEvent *event) override; virtual void Retranslate() override; public slots: void paste(bool insert = false); @@ -233,8 +231,8 @@ public slots: void edit_to_in_point(); void edit_to_out_point(); - void increase_track_height(); - void decrease_track_height(); + void IncreaseTrackHeight(); + void DecreaseTrackHeight(); void previous_cut(); void next_cut(); @@ -268,12 +266,12 @@ private: void setup_ui(); - int default_track_height; - // ripple delete empty space variables long rc_ripple_min; long rc_ripple_max; + QVector track_heights; + QWidget* timeline_area; TimelineWidget* video_area; TimelineWidget* audio_area; diff --git a/panels/viewer.cpp b/panels/viewer.cpp index 927277f6c..79d5321ef 100644 --- a/panels/viewer.cpp +++ b/panels/viewer.cpp @@ -66,8 +66,6 @@ Viewer::Viewer(QWidget *parent) : cue_recording_internal(false), playback_speed(0) { - setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - setup_ui(); headers->viewer = this; diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index 3a2acec10..ee22bf168 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -1,4 +1,4 @@ -/*** +/*** Olive - Non-Linear Video Editor Copyright (C) 2019 Olive Team @@ -566,42 +566,53 @@ void TimelineWidget::mouseDoubleClickEvent(QMouseEvent *event) { } } -bool isLiveEditing() { +bool current_tool_shows_cursor() { return (panel_timeline->tool == TIMELINE_TOOL_EDIT || panel_timeline->tool == TIMELINE_TOOL_RAZOR || panel_timeline->creating); } void TimelineWidget::mousePressEvent(QMouseEvent *event) { if (olive::ActiveSequence != nullptr) { - int tool = panel_timeline->tool; + + int effective_tool = panel_timeline->tool; + + // some user actions will override which tool we'll be using if (event->button() == Qt::MiddleButton) { - tool = TIMELINE_TOOL_HAND; + effective_tool = TIMELINE_TOOL_HAND; panel_timeline->creating = false; } else if (event->button() == Qt::RightButton) { - tool = TIMELINE_TOOL_MENU; + effective_tool = TIMELINE_TOOL_MENU; panel_timeline->creating = false; } - QPoint pos = event->pos(); - if (isLiveEditing()) { - panel_timeline->drag_frame_start = panel_timeline->cursor_frame; - panel_timeline->drag_track_start = panel_timeline->cursor_track; - } else { - panel_timeline->drag_frame_start = panel_timeline->getTimelineFrameFromScreenPoint(pos.x()); - panel_timeline->drag_track_start = getTrackFromScreenPoint(pos.y()); - } + // ensure cursor_frame and cursor_track are up to date + mouseMoveEvent(event); - int clip_index = panel_timeline->trim_target; - if (clip_index == -1) clip_index = getClipIndexFromCoords(panel_timeline->drag_frame_start, panel_timeline->drag_track_start); + // store current cursor positions + panel_timeline->drag_x_start = event->pos().x(); + panel_timeline->drag_y_start = event->pos().y(); + + // store current frame/tracks as the values to start dragging from + panel_timeline->drag_frame_start = panel_timeline->cursor_frame; + panel_timeline->drag_track_start = panel_timeline->cursor_track; + + // get the clip the user is currently hovering over, priority to trim_target set from mouseMoveEvent + int hovered_clip = panel_timeline->trim_target == -1 ? + getClipIndexFromCoords(panel_timeline->cursor_frame, panel_timeline->cursor_track) + : panel_timeline->trim_target; bool shift = (event->modifiers() & Qt::ShiftModifier); bool alt = (event->modifiers() & Qt::AltModifier); + // Normal behavior is to reset selections to zero when clicking, but if Shift is held, we add selections + // to the existing selections. `selection_offset` is the index to change selections from (and we don't touch + // any prior to that) if (shift) { panel_timeline->selection_offset = olive::ActiveSequence->selections.size(); } else { panel_timeline->selection_offset = 0; } + // if the user is creating an object if (panel_timeline->creating) { int comp = 0; switch (panel_timeline->creating_object) { @@ -617,21 +628,26 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) { break; } + // if the track the user clicked is correct for the type of object we're adding + if ((panel_timeline->drag_track_start < 0) == (comp < 0)) { Ghost g; g.in = g.old_in = g.out = g.old_out = panel_timeline->drag_frame_start; g.track = g.old_track = panel_timeline->drag_track_start; g.transition = nullptr; g.clip = -1; - g.trimming = true; - g.trim_in = false; + g.trim_type = TRIM_OUT; panel_timeline->ghosts.append(g); panel_timeline->moving_init = true; panel_timeline->moving_proc = true; } } else { - switch (tool) { + + // pass through tools to determine what action we'll be starting + switch (effective_tool) { + + // many tools share pointer-esque behavior case TIMELINE_TOOL_POINTER: case TIMELINE_TOOL_RIPPLE: case TIMELINE_TOOL_SLIP: @@ -639,125 +655,181 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) { case TIMELINE_TOOL_SLIDE: case TIMELINE_TOOL_MENU: { - if (track_resizing && tool != TIMELINE_TOOL_MENU) { - track_resize_mouse_cache = event->pos().y(); + if (track_resizing && effective_tool != TIMELINE_TOOL_MENU) { + + // if the cursor is currently hovering over a track, init track resizing panel_timeline->moving_init = true; + } else { - if (clip_index >= 0) { - ClipPtr clip = olive::ActiveSequence->clips.at(clip_index); - if (clip != nullptr) { - if (is_clip_selected(clip, true)) { - if (shift) { - panel_timeline->deselect_area(clip->timeline_in, clip->timeline_out, clip->track); - if (!alt) { - for (int i=0;ilinked.size();i++) { - ClipPtr link = olive::ActiveSequence->clips.at(clip->linked.at(i)); - panel_timeline->deselect_area(link->timeline_in, link->timeline_out, link->track); - } - } - } else if (panel_timeline->tool == TIMELINE_TOOL_POINTER && panel_timeline->transition_select != kTransitionNone) { - panel_timeline->deselect_area(clip->timeline_in, clip->timeline_out, clip->track); + // check if we're currently hovering over a clip or not + if (hovered_clip >= 0) { + ClipPtr clip = olive::ActiveSequence->clips.at(hovered_clip); + if (is_clip_selected(clip, true)) { + + if (shift) { + + // if the user clicks a selected clip while holding shift, deselect the clip + panel_timeline->deselect_area(clip->timeline_in, clip->timeline_out, clip->track); + + // if the user isn't holding alt, also deselect all of its links + if (!alt) { for (int i=0;ilinked.size();i++) { ClipPtr link = olive::ActiveSequence->clips.at(clip->linked.at(i)); panel_timeline->deselect_area(link->timeline_in, link->timeline_out, link->track); } - - Selection s; - s.track = clip->track; - - if (panel_timeline->transition_select == kTransitionOpening && clip->get_opening_transition() != nullptr) { - s.in = clip->timeline_in; - if (clip->get_opening_transition()->secondary_clip != nullptr) s.in -= clip->get_opening_transition()->get_true_length(); - s.out = clip->timeline_in + clip->get_opening_transition()->get_true_length(); - } else if (panel_timeline->transition_select == kTransitionClosing && clip->get_closing_transition() != nullptr) { - s.in = clip->timeline_out - clip->get_closing_transition()->get_true_length(); - s.out = clip->timeline_out; - if (clip->get_closing_transition()->secondary_clip != nullptr) s.out += clip->get_closing_transition()->get_true_length(); - } - olive::ActiveSequence->selections.append(s); } - } else { - // if "shift" is not down - if (!shift) { - olive::ActiveSequence->selections.clear(); + + } else if (panel_timeline->tool == TIMELINE_TOOL_POINTER && panel_timeline->transition_select != kTransitionNone) { + + + + panel_timeline->deselect_area(clip->timeline_in, clip->timeline_out, clip->track); + + for (int i=0;ilinked.size();i++) { + ClipPtr link = olive::ActiveSequence->clips.at(clip->linked.at(i)); + panel_timeline->deselect_area(link->timeline_in, link->timeline_out, link->track); } Selection s; - - s.in = clip->timeline_in; - s.out = clip->timeline_out; - - if (panel_timeline->tool == TIMELINE_TOOL_POINTER) { - if (panel_timeline->transition_select == kTransitionOpening) { - s.out = clip->timeline_in + clip->get_opening_transition()->get_true_length(); - if (clip->get_opening_transition()->secondary_clip != nullptr) s.in -= clip->get_opening_transition()->get_true_length(); - } - - if (panel_timeline->transition_select == kTransitionClosing) { - s.in = clip->timeline_out - clip->get_closing_transition()->get_true_length(); - if (clip->get_closing_transition()->secondary_clip != nullptr) s.out += clip->get_closing_transition()->get_true_length(); - } - } - s.track = clip->track; - olive::ActiveSequence->selections.append(s); - if (olive::CurrentConfig.select_also_seeks) { - panel_sequence_viewer->seek(clip->timeline_in); + if (panel_timeline->transition_select == kTransitionOpening && clip->get_opening_transition() != nullptr) { + s.in = clip->timeline_in; + if (clip->get_opening_transition()->secondary_clip != nullptr) s.in -= clip->get_opening_transition()->get_true_length(); + s.out = clip->timeline_in + clip->get_opening_transition()->get_true_length(); + } else if (panel_timeline->transition_select == kTransitionClosing && clip->get_closing_transition() != nullptr) { + s.in = clip->timeline_out - clip->get_closing_transition()->get_true_length(); + s.out = clip->timeline_out; + if (clip->get_closing_transition()->secondary_clip != nullptr) s.out += clip->get_closing_transition()->get_true_length(); } + olive::ActiveSequence->selections.append(s); + } + } else { - // if alt is not down, select links - if (!alt && panel_timeline->transition_select == kTransitionNone) { - for (int i=0;ilinked.size();i++) { - ClipPtr link = olive::ActiveSequence->clips.at(clip->linked.at(i)); - if (!is_clip_selected(link, true)) { - Selection ss; - ss.in = link->timeline_in; - ss.out = link->timeline_out; - ss.track = link->track; - olive::ActiveSequence->selections.append(ss); - } + // if the clip is not already selected + + // if shift is NOT down, we change clear all current selections + if (!shift) { + olive::ActiveSequence->selections.clear(); + } + + Selection s; + + s.in = clip->timeline_in; + s.out = clip->timeline_out; + s.track = clip->track; + + // if user is using the pointer tool, they may be trying to select a transition + // check if the use is hovering over a transition + if (panel_timeline->tool == TIMELINE_TOOL_POINTER) { + if (panel_timeline->transition_select == kTransitionOpening) { + // move the selection to only select the transitoin + s.out = clip->timeline_in + clip->get_opening_transition()->get_true_length(); + + // if the transition is a "shared" transition, adjust the selection to select both sides + if (clip->get_opening_transition()->secondary_clip != nullptr) { + s.in -= clip->get_opening_transition()->get_true_length(); + } + } else if (panel_timeline->transition_select == kTransitionClosing) { + // move the selection to only select the transitoin + s.in = clip->timeline_out - clip->get_closing_transition()->get_true_length(); + + // if the transition is a "shared" transition, adjust the selection to select both sides + if (clip->get_closing_transition()->secondary_clip != nullptr) { + s.out += clip->get_closing_transition()->get_true_length(); } } } + + // add the selection to the array + olive::ActiveSequence->selections.append(s); + + // if the config is set to also seek with selections, do so now + if (olive::CurrentConfig.select_also_seeks) { + panel_sequence_viewer->seek(clip->timeline_in); + } + + // if alt is not down, select links (provided we're not selecting transitions) + if (!alt && panel_timeline->transition_select == kTransitionNone) { + + for (int i=0;ilinked.size();i++) { + + ClipPtr link = olive::ActiveSequence->clips.at(clip->linked.at(i)); + + // check if the clip is already selected + if (!is_clip_selected(link, true)) { + Selection ss; + ss.in = link->timeline_in; + ss.out = link->timeline_out; + ss.track = link->track; + olive::ActiveSequence->selections.append(ss); + } + + } + + } + } + + // authorize the starting of a move action if the mouse moves after this + if (effective_tool != TIMELINE_TOOL_MENU) { + panel_timeline->moving_init = true; } - if (tool != TIMELINE_TOOL_MENU) panel_timeline->moving_init = true; } else { - // if "shift" is not down + + // if the user did not click a clip at all, we start a rectangle selection + if (!shift) { olive::ActiveSequence->selections.clear(); } panel_timeline->rect_select_init = true; } + + // update everything update_ui(false); } } break; case TIMELINE_TOOL_HAND: + + // initiate moving with the hand tool panel_timeline->hand_moving = true; - panel_timeline->drag_x_start = pos.x(); - panel_timeline->drag_y_start = pos.y(); + break; case TIMELINE_TOOL_EDIT: - if (olive::CurrentConfig.edit_tool_also_seeks) panel_sequence_viewer->seek(panel_timeline->drag_frame_start); + + // if the config is set to seek with the edit tool, do so now + if (olive::CurrentConfig.edit_tool_also_seeks) { + panel_sequence_viewer->seek(panel_timeline->drag_frame_start); + } + + // initiate selecting panel_timeline->selecting = true; + break; case TIMELINE_TOOL_RAZOR: { + + // initiate razor tool panel_timeline->splitting = true; + + // add this track as a track being split by the razor panel_timeline->split_tracks.append(panel_timeline->drag_track_start); + update_ui(false); } break; case TIMELINE_TOOL_TRANSITION: { + + // if there is a clip to run the transition tool on, initiate the transition tool if (panel_timeline->transition_tool_pre_clip > -1) { panel_timeline->transition_tool_init = true; } + } break; } @@ -906,7 +978,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { // 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) - if (panel_timeline->trim_in_point) { + if (panel_timeline->trim_type == TRIM_IN) { ripple_length = first_ghost.old_in - first_ghost.in; ripple_point = first_ghost.old_in; @@ -924,16 +996,16 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { const Ghost& g = panel_timeline->ghosts.at(i); // push rippled clips forward if necessary - if (panel_timeline->trim_in_point) { + if (panel_timeline->trim_type == TRIM_IN) { ignore_clips.append(g.clip); panel_timeline->ghosts[i].in += ripple_length; panel_timeline->ghosts[i].out += ripple_length; } - long comp_point = panel_timeline->trim_in_point ? g.old_in : g.old_out; + long comp_point = (panel_timeline->trim_type == TRIM_IN) ? g.old_in : g.old_out; ripple_point = qMin(ripple_point, comp_point); } - if (!panel_timeline->trim_in_point) ripple_length = -ripple_length; + if (panel_timeline->trim_type == TRIM_OUT) ripple_length = -ripple_length; ripple_clips(ca, olive::ActiveSequence, ripple_point, ripple_length, ignore_clips); } @@ -1018,7 +1090,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { long new_clip_length = (g.out - g.in); if (c->get_opening_transition() != nullptr) { long max_open_length = new_clip_length; - if (c->get_closing_transition() != nullptr && !panel_timeline->trim_in_point) { + if (c->get_closing_transition() != nullptr && panel_timeline->trim_type == TRIM_OUT) { max_open_length -= c->get_closing_transition()->get_true_length(); } if (max_open_length <= 0) { @@ -1029,7 +1101,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { } if (c->get_closing_transition() != nullptr) { long max_open_length = new_clip_length; - if (c->get_opening_transition() != nullptr && panel_timeline->trim_in_point) { + if (c->get_opening_transition() != nullptr && panel_timeline->trim_type == TRIM_IN) { max_open_length -= c->get_opening_transition()->get_true_length(); } if (max_open_length <= 0) { @@ -1047,7 +1119,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { long clip_length = c->getLength(); if (g.transition->secondary_clip != nullptr) { - if (g.in != g.old_in && !g.trimming) { + if (g.in != g.old_in && g.trim_type == TRIM_NONE) { long movement = g.in - g.old_in; move_clip(ca, g.transition->parent_clip, movement, 0, movement, 0, false, true); move_clip(ca, g.transition->secondary_clip, 0, movement, 0, 0, false, true); @@ -1287,7 +1359,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { const Ghost& g = panel_timeline->ghosts.at(i); // snap ghost's in point - if (panel_timeline->trim_target == -1 || g.trim_in) { + if (panel_timeline->trim_target == -1 || g.trim_type == TRIM_IN) { fm = g.old_in + frame_diff; if (panel_timeline->snap_to_timeline(&fm, true, true, true)) { frame_diff = fm - g.old_in; @@ -1296,7 +1368,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { } // snap ghost's out point - if (panel_timeline->trim_target == -1 || !g.trim_in) { + if (panel_timeline->trim_target == -1 || g.trim_type == TRIM_OUT) { fm = g.old_out + frame_diff; if (panel_timeline->snap_to_timeline(&fm, true, true, true)) { frame_diff = fm - g.old_out; @@ -1347,8 +1419,8 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { validator += g.ghost_length; if (validator > g.media_length) frame_diff += validator - g.media_length; } - } else if (g.trimming) { - if (g.trim_in) { + } else if (g.trim_type != TRIM_NONE) { + if (g.trim_type == TRIM_IN) { // prevent clip/transition length from being less than 1 frame long validator = g.ghost_length - frame_diff; if (validator < 1) frame_diff -= (1 - validator); @@ -1383,7 +1455,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { ClipPtr otc = g.transition->parent_clip; ClipPtr ctc = g.transition->secondary_clip; - if (g.trim_in) { + if (g.trim_type == TRIM_IN) { frame_diff -= g.transition->get_true_length(); } else { frame_diff += g.transition->get_true_length(); @@ -1397,7 +1469,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { validate_transitions(ctc, kTransitionClosing, frame_diff); frame_diff = -frame_diff; - if (g.trim_in) { + if (g.trim_type == TRIM_IN) { frame_diff += g.transition->get_true_length(); } else { frame_diff -= g.transition->get_true_length(); @@ -1410,7 +1482,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { ClipPtr post = post_clips.at(j); // prevent any rippled clip from going below 0 - if (panel_timeline->trim_in_point) { + if (panel_timeline->trim_type == TRIM_IN) { validator = post->timeline_in - frame_diff; if (validator < 0) frame_diff += validator; } @@ -1419,7 +1491,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { for (int k=0;ktrack == post->track) { - if (panel_timeline->trim_in_point) { + if (panel_timeline->trim_type == TRIM_IN) { validator = post->timeline_in - frame_diff - pre->timeline_out; if (validator < 0) frame_diff += validator; } else { @@ -1511,7 +1583,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { if (effective_tool == TIMELINE_TOOL_SLIP) { g.clip_in = g.old_clip_in - frame_diff; - } else if (g.trimming) { + } else if (g.trim_type != TRIM_NONE) { long ghost_diff = frame_diff; // prevent trimming clips from overlapping each other @@ -1519,7 +1591,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { const Ghost& comp = panel_timeline->ghosts.at(j); if (i != j && g.track == comp.track) { long validator; - if (g.trim_in && comp.out < g.out) { + if (g.trim_type == TRIM_IN && comp.out < g.out) { validator = (g.old_in + ghost_diff) - comp.out; if (validator < 0) ghost_diff -= validator; } else if (comp.in > g.in) { @@ -1531,10 +1603,10 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { // apply changes if (g.transition != nullptr && g.transition->secondary_clip != nullptr) { - if (g.trim_in) ghost_diff = -ghost_diff; + if (g.trim_type == TRIM_IN) ghost_diff = -ghost_diff; g.in = g.old_in - ghost_diff; g.out = g.old_out + ghost_diff; - } else if (g.trim_in) { + } else if (g.trim_type == TRIM_IN) { g.in = g.old_in + ghost_diff; g.clip_in = g.old_clip_in + ghost_diff; } else { @@ -1581,7 +1653,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { for (int i=0;iselections.size();i++) { Selection& s = olive::ActiveSequence->selections[i]; if (panel_timeline->trim_target > -1) { - if (panel_timeline->trim_in_point) { + if (panel_timeline->trim_type == TRIM_IN) { s.in = s.old_in + frame_diff; } else { s.out = s.old_out + frame_diff; @@ -1625,7 +1697,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { if (g != nullptr) { tip += " " + tr("Duration:") + " "; long len = (g->old_out-g->old_in); - if (panel_timeline->trim_in_point) { + if (panel_timeline->trim_type == TRIM_IN) { len -= frame_diff; } else { len += frame_diff; @@ -1638,228 +1710,272 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { } void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { + // interrupt any potential tooltip about to show tooltip_timer.stop(); + if (olive::ActiveSequence != nullptr) { bool alt = (event->modifiers() & Qt::AltModifier); + // store current frame/track corresponding to the cursor panel_timeline->cursor_frame = panel_timeline->getTimelineFrameFromScreenPoint(event->pos().x()); panel_timeline->cursor_track = getTrackFromScreenPoint(event->pos().y()); - panel_timeline->move_insert = ((event->modifiers() & Qt::ControlModifier) && (panel_timeline->tool == TIMELINE_TOOL_POINTER || panel_timeline->importing || panel_timeline->creating)); + // determine if the action should be "inserting" rather than "overwriting" + // Default behavior is to replace/overwrite clips under any clips we're dropping over them. Inserting will + // split and move existing clips at the drop point to make space for the drop + panel_timeline->move_insert = ((event->modifiers() & Qt::ControlModifier) + && (panel_timeline->tool == TIMELINE_TOOL_POINTER + || panel_timeline->importing + || panel_timeline->creating)); - if (!panel_timeline->moving_init) track_resizing = false; - - if (isLiveEditing()) { - panel_timeline->snap_to_timeline(&panel_timeline->cursor_frame, !olive::CurrentConfig.edit_tool_also_seeks || !panel_timeline->selecting, true, true); + // if we're not currently resizing already, default track resizing to false (we'll set it to true later if + // the user is still hovering over a track line) + if (!panel_timeline->moving_init) { + track_resizing = false; } + + // if the current tool uses an on-screen visible cursor, we snap the cursor to the timeline + if (current_tool_shows_cursor()) { + panel_timeline->snap_to_timeline(&panel_timeline->cursor_frame, + + // only snap to the playhead if the edit tool doesn't force the playhead to + // follow it (or if we're not selecting since that means the playhead is + // static at the moment) + !olive::CurrentConfig.edit_tool_also_seeks || !panel_timeline->selecting, + + true, + true); + } + 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; + + // get number of selections based on tracks in selection area + int selection_tool_count = 1 + qMax(panel_timeline->cursor_track, panel_timeline->drag_track_start) - qMin(panel_timeline->cursor_track, panel_timeline->drag_track_start); + + // add count to selection offset for the total number of selection objects + // (offset is usually 0, unless the user is holding shift in which case we add to existing selections) + int selection_count = selection_tool_count + panel_timeline->selection_offset; + + // resize selection object array to new count if (olive::ActiveSequence->selections.size() != selection_count) { olive::ActiveSequence->selections.resize(selection_count); } + + // loop through tracks in selection area and adjust them accordingly int minimum_selection_track = qMin(panel_timeline->cursor_track, panel_timeline->drag_track_start); + int maximum_selection_track = qMax(panel_timeline->cursor_track, panel_timeline->drag_track_start); + long selection_in = qMin(panel_timeline->drag_frame_start, panel_timeline->cursor_frame); + long selection_out = qMax(panel_timeline->drag_frame_start, panel_timeline->cursor_frame); 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); + s.in = selection_in; + s.out = selection_out; } - // select linked clips too + // If the config is set to select links as well with the edit tool if (olive::CurrentConfig.edit_tool_selects_links) { - for (int j=0;jclips.size();j++) { - ClipPtr c = olive::ActiveSequence->clips.at(j); - for (int k=0;kselections.size();k++) { - const Selection& s = olive::ActiveSequence->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 = olive::ActiveSequence->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; - link_sel.in = s.in; - link_sel.out = s.out; - link_sel.track = linked_tracks.at(k); - olive::ActiveSequence->selections.append(link_sel); - } + // find which clips are selected + for (int j=0;jclips.size();j++) { + + ClipPtr c = olive::ActiveSequence->clips.at(j); + + if (c != nullptr && is_clip_selected(c, false)) { + + // loop through linked clips + for (int k=0;klinked.size();k++) { + + ClipPtr link = olive::ActiveSequence->clips.at(c->linked.at(k)); + + // see if one of the selections is already covering this track + if (!(link->track >= minimum_selection_track + && link->track <= maximum_selection_track)) { + + // clip is not in selectin area, time to select it + Selection link_sel; + link_sel.in = selection_in; + link_sel.out = selection_out; + link_sel.track = link->track; + olive::ActiveSequence->selections.append(link_sel); + } - break; } + } } } + // if the config is set to seek with the edit too, do so now if (olive::CurrentConfig.edit_tool_also_seeks) { panel_sequence_viewer->seek(qMin(panel_timeline->drag_frame_start, panel_timeline->cursor_frame)); } else { + // if not, repaint (seeking will trigger a repaint) panel_timeline->repaint_timeline(); } + } else if (panel_timeline->hand_moving) { + + // if we're hand moving, we'll be adding values directly to the scrollbars + + // the scrollbars trigger repaints when they scroll, which is unnecessary here so we block them panel_timeline->block_repaints = true; panel_timeline->horizontalScrollBar->setValue(panel_timeline->horizontalScrollBar->value() + panel_timeline->drag_x_start - event->pos().x()); scrollBar->setValue(scrollBar->value() + panel_timeline->drag_y_start - event->pos().y()); panel_timeline->block_repaints = false; + // finally repaint panel_timeline->repaint_timeline(); + // store current cursor position for next hand move event panel_timeline->drag_x_start = event->pos().x(); panel_timeline->drag_y_start = event->pos().y(); + } 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; + + // get cursor movement + int diff = (event->pos().y() - panel_timeline->drag_y_start); + + // add it to the current track height + int new_height = panel_timeline->GetTrackHeight(track_target); if (bottom_align) { - new_height += diff; - } else { new_height -= diff; + } else { + new_height += diff; } + + // limit track height to track minimum height constant new_height = qMax(new_height, olive::timeline::kTrackMinHeight); - panel_timeline->calculate_track_height(track_target, new_height); + + // set the track height + panel_timeline->SetTrackHeight(track_target, new_height); + + // store current cursor position for next track resize event + panel_timeline->drag_y_start = event->pos().y(); + update(); } else if (panel_timeline->moving_proc) { + + // we're currently dragging ghosts update_ghosts(event->pos(), event->modifiers() & Qt::ShiftModifier); + } else { - // set up movement - // create ghosts + + // Prepare to start moving clips in some capacity. We create Ghost objects to store movement data before we + // actually apply it to the clips (in mouseReleaseEvent) + + // loop through clips for any currently selected for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr) { Ghost g; g.transition = nullptr; + // check if whole clip is added bool add = is_clip_selected(c, true); // if a whole clip is not selected, maybe just a transition is - if (panel_timeline->tool == TIMELINE_TOOL_POINTER && (c->get_opening_transition() != nullptr || c->get_closing_transition() != nullptr)) { - // check if any selections contain the whole clip or transition + // (only the pointer tool supports moving transitions) + if (!add + && panel_timeline->tool == TIMELINE_TOOL_POINTER + && (c->get_opening_transition() != nullptr || c->get_closing_transition() != nullptr)) { + + // check if any selections contain a whole transition for (int j=0;jselections.size();j++) { + const Selection& s = olive::ActiveSequence->selections.at(j); + if (s.track == c->track) { if (selection_contains_transition(s, c, kTransitionOpening)) { + g.transition = c->get_opening_transition(); add = true; break; + } else if (selection_contains_transition(s, c, kTransitionClosing)) { + g.transition = c->get_closing_transition(); add = true; break; + } } - } - } - if (add && g.transition != nullptr) { - // check for duplicate transitions - for (int j=0;jghosts.size();j++) { - if (panel_timeline->ghosts.at(j).transition == g.transition) { - add = false; - break; - } } + } if (add) { - g.clip = i; - g.trimming = (panel_timeline->trim_target > -1); - g.trim_in = panel_timeline->trim_in_point; - panel_timeline->ghosts.append(g); + + if (g.transition != nullptr) { + + // transition may be a dual transition, check if it's already been added elsewhere + for (int j=0;jghosts.size();j++) { + if (panel_timeline->ghosts.at(j).transition == g.transition) { + add = false; + break; + } + } + + } + + if (add) { + g.clip = i; + g.trim_type = panel_timeline->trim_type; + panel_timeline->ghosts.append(g); + } + } } } - int size = panel_timeline->ghosts.size(); - if (panel_timeline->tool == TIMELINE_TOOL_ROLLING) { - for (int i=0;iclips.at(panel_timeline->ghosts.at(i).clip); + if (panel_timeline->tool == TIMELINE_TOOL_SLIDE) { - // see if any ghosts are touching, in which case flip them - for (int k=0;kclips.at(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; - } - } - } + // for the slide tool, we add the surrounding clips as ghosts that are getting trimmed the opposite way - // then look for other clips we're touching - for (int i=0;ighosts.at(i); - ClipPtr ghost_clip = olive::ActiveSequence->clips.at(g.clip); - for (int j=0;jclips.size();j++) { - ClipPtr comp_clip = olive::ActiveSequence->clips.at(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 + // store original array size since we'll be adding to it + int ghost_arr_size = panel_timeline->ghosts.size(); + + // loop through clips for any that are "touching" the selected clips + for (int j=0;jclips.size();j++) { + + ClipPtr c = olive::ActiveSequence->clips.at(j); + if (c != nullptr) { + + for (int i=0;ighosts[i]; + g.trim_type = TRIM_NONE; // the selected clips will be moving, not trimming + + ClipPtr ghost_clip = olive::ActiveSequence->clips.at(g.clip); + + if (c->track == ghost_clip->track) { + + // see if this clip is currently selected, if so we won't add it as a "touching" clip bool found = false; - int duplicate_ghost_index; - for (duplicate_ghost_index=0;duplicate_ghost_indexghosts.at(duplicate_ghost_index).clip == j) { + for (int k=0;kghosts.at(k).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 + + if (!found) { // the clip is not currently selected + + // check if this clip is indeed touching + bool is_in = (c->timeline_in == ghost_clip->timeline_out); + if (is_in || c->timeline_out == ghost_clip->timeline_in) { Ghost gh; gh.transition = nullptr; gh.clip = j; - gh.trimming = (panel_timeline->trim_target > -1); - gh.trim_in = !panel_timeline->trim_in_point; + gh.trim_type = is_in ? TRIM_IN : TRIM_OUT; panel_timeline->ghosts.append(gh); } - } else { - if (found) { - panel_timeline->ghosts.removeAt(duplicate_ghost_index); - size--; - if (duplicate_ghost_index < i) i--; - } - } - } - } - } - } - } else if (panel_timeline->tool == TIMELINE_TOOL_SLIDE) { - for (int i=0;ighosts.at(i); - ClipPtr ghost_clip = olive::ActiveSequence->clips.at(g.clip); - panel_timeline->ghosts[i].trimming = false; - for (int j=0;jclips.size();j++) { - ClipPtr c = olive::ActiveSequence->clips.at(j); - if (c != nullptr && 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.transition = nullptr; - gh.clip = j; - gh.trimming = true; - gh.trim_in = is_in; - panel_timeline->ghosts.append(gh); } } } @@ -1867,40 +1983,61 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { } } + // set up ghost defaults init_ghosts(); - // ripple edit prep + // if the ripple tool is selected, prepare to ripple if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) { + long axis = LONG_MAX; + // find the earliest point within the selected clips which is the point we'll ripple around + // also store the currently selected clips so we don't have to do it later + QVector ghost_clips; + ghost_clips.resize(panel_timeline->ghosts.size()); + for (int i=0;ighosts.size();i++) { ClipPtr c = olive::ActiveSequence->clips.at(panel_timeline->ghosts.at(i).clip); - if (panel_timeline->trim_in_point) { + if (panel_timeline->trim_type == TRIM_IN) { axis = qMin(axis, c->timeline_in); } else { axis = qMin(axis, c->timeline_out); } + + // store clip reference + ghost_clips[i] = c; } + // loop through clips and cache which are earlier than the axis and which after after for (int i=0;iclips.size();i++) { ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr && !is_clip_selected(c, true)) { + if (c != nullptr && !ghost_clips.contains(c)) { bool clip_is_post = (c->timeline_in >= axis); - // see if this a clip on this track is already in the list, and if it's closer + // construct the list of pre and post clips + QVector& clip_list = (clip_is_post) ? post_clips : pre_clips; + + // check if there's already a clip in this list on this track, and if this clip is closer or not bool found = false; - QVector& clip_list = clip_is_post ? post_clips : pre_clips; for (int j=0;jtrack == c->track) { + + // if the clip is closer, use this one instead of the current one in the list if ((!clip_is_post && compare->timeline_out < c->timeline_out) || (clip_is_post && compare->timeline_in > c->timeline_in)) { clip_list[j] = c; } + found = true; break; } + } + + // if there is no clip on this track in the list, add it if (!found) { clip_list.append(c); } @@ -1912,48 +2049,76 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { selection_command = new SetSelectionsCommand(olive::ActiveSequence); selection_command->old_data = olive::ActiveSequence->selections; + // ready to start moving clips panel_timeline->moving_proc = true; } + update_ui(false); + } else if (panel_timeline->splitting) { + + // get the range of tracks currently dragged 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_end = qMax(panel_timeline->cursor_track, panel_timeline->drag_track_start); int track_size = 1 + track_end - track_start; + + // set tracks to be split panel_timeline->split_tracks.resize(track_size); for (int i=0;isplit_tracks[i] = track_start + i; } + // if alt isn't being held, also add the tracks of the clip's links 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)); + ClipPtr clip = olive::ActiveSequence->clips.at(clip_index); + for (int j=0;jlinked.size();j++) { + + ClipPtr link = olive::ActiveSequence->clips.at(clip->linked.at(j)); + + // if this clip isn't already in the list of tracks to split + if (link->track < track_start || link->track > track_end) { + panel_timeline->split_tracks.append(link->track); } + } } } } - update_ui(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(); - long frame_start = panel_timeline->getTimelineFrameFromScreenPoint(panel_timeline->rect_select_x); - long frame_end = panel_timeline->getTimelineFrameFromScreenPoint(event->pos().x()); + update_ui(false); + + } else if (panel_timeline->rect_select_init) { + + // set if the user started dragging at point where there was no clip + + if (panel_timeline->rect_select_proc) { + + // we're currently rectangle selecting + + // set the right/bottom coords to the current mouse position + // (left/top were set to the starting drag position earlier) + panel_timeline->rect_select_rect.setRight(event->pos().x()); + + if (bottom_align) { + panel_timeline->rect_select_rect.setBottom(event->pos().y() - height()); + } else { + panel_timeline->rect_select_rect.setBottom(event->pos().y()); + } + + long frame_start = panel_timeline->drag_frame_start; + long frame_end = panel_timeline->cursor_frame; 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_start = panel_timeline->drag_track_start; + int track_end = panel_timeline->cursor_track; + int track_min = qMin(track_start, track_end); int track_max = qMax(track_start, track_end); @@ -2002,14 +2167,20 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { 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_rect.setX(event->pos().x()); + + if (bottom_align) { + panel_timeline->rect_select_rect.setY(event->pos().y() - height()); + } else { + panel_timeline->rect_select_rect.setY(event->pos().y()); + } + + panel_timeline->rect_select_rect.setWidth(0); + panel_timeline->rect_select_rect.setHeight(0); + panel_timeline->rect_select_proc = true; } - } else if (isLiveEditing()) { + } else if (current_tool_shows_cursor()) { // redraw because we have a cursor panel_timeline->repaint_timeline(); } else if (panel_timeline->tool == TIMELINE_TOOL_POINTER || @@ -2031,9 +2202,6 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { long mouse_frame_lower = panel_timeline->getTimelineFrameFromScreenPoint(pos.x()-lim)-1; long mouse_frame_upper = panel_timeline->getTimelineFrameFromScreenPoint(pos.x()+lim)+1; - // current track that the cursor is on - int mouse_track = getTrackFromScreenPoint(pos.y()); - // used to determine whether we the cursor found a trim point or not bool found = false; @@ -2051,6 +2219,9 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { // we default to selecting no transition, but set this accordingly if the cursor is on a transition panel_timeline->transition_select = kTransitionNone; + // we also default to no trimming which may be changed later in this function + panel_timeline->trim_type = TRIM_NONE; + // set currently trimming clip to -1 (aka null) panel_timeline->trim_target = -1; @@ -2064,7 +2235,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { max_track = qMax(max_track, c->track); // if this clip is on the same track the mouse is - if (c->track == mouse_track) { + if (c->track == panel_timeline->cursor_track) { // if this cursor is inside the boundaries of this clip (hovering over the clip) if (panel_timeline->cursor_frame >= c->timeline_in && @@ -2102,7 +2273,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { // if so, this is the point we'll make active for now (unless we find a closer one later) panel_timeline->trim_target = i; - panel_timeline->trim_in_point = true; + panel_timeline->trim_type = TRIM_IN; closeness = nc; found = true; @@ -2120,7 +2291,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { // if so, this is the point we'll make active for now (unless we find a closer one later) panel_timeline->trim_target = i; - panel_timeline->trim_in_point = false; + panel_timeline->trim_type = TRIM_OUT; closeness = nc; found = true; @@ -2144,7 +2315,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { 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->trim_type = TRIM_OUT; panel_timeline->transition_select = kTransitionOpening; closeness = nc; found = true; @@ -2165,7 +2336,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { 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->trim_type = TRIM_IN; panel_timeline->transition_select = kTransitionClosing; closeness = nc; found = true; @@ -2180,7 +2351,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { // if the cursor is indeed on a clip edge, we set the cursor accordingly if (found) { - if (panel_timeline->trim_in_point) { // if we're trimming an IN point + if (panel_timeline->trim_type == TRIM_IN) { // if we're trimming an IN point setCursor(olive::Cursor_LeftTrim); } else { // if we're trimming an OUT point setCursor(olive::Cursor_RightTrim); @@ -2190,33 +2361,28 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { // we didn't find a trim target, so we must be doing something else // (e.g. dragging a clip or resizing the track heights) + unsetCursor(); + // check to see if we're resizing a track height - int track_y = 0; - for (int i=0;iget_track_height_size(bottom_align);i++) { - int track = (bottom_align) ? -1-i : i; - 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 (olive::CurrentConfig.show_track_lines || cursor_contains_clip) { - found = true; - track_resizing = true; - track_target = track; - track_resize_old_value = track_height; - } - break; - } - } + int test_range = 5; + int mouse_pos = event->pos().y() + scroll; + int hover_track = getTrackFromScreenPoint(mouse_pos); + int track_y_edge = getScreenPointFromTrack(hover_track); + + if (!bottom_align) { + track_y_edge += panel_timeline->GetTrackHeight(hover_track); } - if (found) { - setCursor(Qt::SizeVerCursor); - } else { - unsetCursor(); + if (mouse_pos > track_y_edge - test_range + && mouse_pos < track_y_edge + test_range) { + if (cursor_contains_clip + || (olive::CurrentConfig.show_track_lines + && panel_timeline->cursor_track >= min_track + && panel_timeline->cursor_track <= max_track)) { + track_resizing = true; + track_target = hover_track; + setCursor(Qt::SizeVerCursor); + } } } } else if (panel_timeline->tool == TIMELINE_TOOL_SLIP) { @@ -2238,7 +2404,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { g.track = c->track; g.clip = panel_timeline->transition_tool_pre_clip; g.media_stream = panel_timeline->transition_tool_type; - g.trimming = false; + g.trim_type = TRIM_NONE; panel_timeline->ghosts.append(g); @@ -2399,14 +2565,17 @@ void TimelineWidget::paintEvent(QPaintEvent*) { } } - int panel_height = TRACK_DEFAULT_HEIGHT; + // start by adding a track height worth of padding + int panel_height = olive::timeline::kTrackDefaultHeight; + + // loop through tracks for maximum panel height if (bottom_align) { for (int i=-1;i>=video_track_limit;i--) { - panel_height += panel_timeline->calculate_track_height(i, -1); + panel_height += panel_timeline->GetTrackHeight(i); } } else { for (int i=0;i<=audio_track_limit;i++) { - panel_height += panel_timeline->calculate_track_height(i, -1); + panel_height += panel_timeline->GetTrackHeight(i); } } if (bottom_align) { @@ -2418,7 +2587,7 @@ void TimelineWidget::paintEvent(QPaintEvent*) { for (int i=0;iclips.size();i++) { ClipPtr clip = olive::ActiveSequence->clips.at(i); if (clip != nullptr && is_track_visible(clip->track)) { - QRect clip_rect(panel_timeline->getTimelineScreenPointFromFrame(clip->timeline_in), getScreenPointFromTrack(clip->track), getScreenPointFromFrame(panel_timeline->zoom, clip->getLength()), panel_timeline->calculate_track_height(clip->track, -1)); + QRect clip_rect(panel_timeline->getTimelineScreenPointFromFrame(clip->timeline_in), getScreenPointFromTrack(clip->track), getScreenPointFromFrame(panel_timeline->zoom, clip->getLength()), panel_timeline->GetTrackHeight(clip->track)); QRect text_rect(clip_rect.left() + olive::timeline::kClipTextPadding, clip_rect.top() + olive::timeline::kClipTextPadding, clip_rect.width() - olive::timeline::kClipTextPadding - 1, clip_rect.height() - olive::timeline::kClipTextPadding - 1); if (clip_rect.left() < width() && clip_rect.right() >= 0 && clip_rect.top() < height() && clip_rect.bottom() >= 0) { QRect actual_clip_rect = clip_rect; @@ -2651,7 +2820,7 @@ void TimelineWidget::paintEvent(QPaintEvent*) { if (panel_sequence_viewer->is_recording_cued() && is_track_visible(panel_sequence_viewer->recording_track)) { int rec_track_x = panel_timeline->getTimelineScreenPointFromFrame(panel_sequence_viewer->recording_start); int rec_track_y = getScreenPointFromTrack(panel_sequence_viewer->recording_track); - int rec_track_height = panel_timeline->calculate_track_height(panel_sequence_viewer->recording_track, -1); + int rec_track_height = panel_timeline->GetTrackHeight(panel_sequence_viewer->recording_track); if (panel_sequence_viewer->recording_start != panel_sequence_viewer->recording_end) { QRect rec_rect( rec_track_x, @@ -2703,7 +2872,7 @@ void TimelineWidget::paintEvent(QPaintEvent*) { } else { // only draw lines for audio tracks for (int i=0;icalculate_track_height(i, -1); + int line_y = getScreenPointFromTrack(i) + panel_timeline->GetTrackHeight(i); p.drawLine(0, line_y, rect().width(), line_y); } } @@ -2717,18 +2886,18 @@ void TimelineWidget::paintEvent(QPaintEvent*) { int selection_x = panel_timeline->getTimelineScreenPointFromFrame(s.in); p.setPen(Qt::NoPen); p.setBrush(Qt::NoBrush); - p.fillRect(selection_x, selection_y, panel_timeline->getTimelineScreenPointFromFrame(s.out) - selection_x, panel_timeline->calculate_track_height(s.track, -1), QColor(0, 0, 0, 64)); + p.fillRect(selection_x, selection_y, panel_timeline->getTimelineScreenPointFromFrame(s.out) - selection_x, panel_timeline->GetTrackHeight(s.track), QColor(0, 0, 0, 64)); } } // draw rectangle select if (panel_timeline->rect_select_proc) { - int rsy = panel_timeline->rect_select_y; - int rsh = panel_timeline->rect_select_h; + QRect rect_select = panel_timeline->rect_select_rect; + if (bottom_align) { - rsy += height(); + rect_select.translate(0, height()); } - QRect rect_select(panel_timeline->rect_select_x, rsy, panel_timeline->rect_select_w, rsh); + draw_selection_rectangle(p, rect_select); } @@ -2743,7 +2912,7 @@ void TimelineWidget::paintEvent(QPaintEvent*) { int ghost_x = panel_timeline->getTimelineScreenPointFromFrame(g.in); int ghost_y = getScreenPointFromTrack(g.track); int ghost_width = panel_timeline->getTimelineScreenPointFromFrame(g.out) - ghost_x - 1; - int ghost_height = panel_timeline->calculate_track_height(g.track, -1) - 1; + int ghost_height = panel_timeline->GetTrackHeight(g.track) - 1; insert_points.append(ghost_y + (ghost_height>>1)); @@ -2781,7 +2950,7 @@ void TimelineWidget::paintEvent(QPaintEvent*) { int cursor_y = getScreenPointFromTrack(panel_timeline->split_tracks.at(i)); p.setPen(QColor(64, 64, 64)); - p.drawLine(cursor_x, cursor_y, cursor_x, cursor_y + panel_timeline->calculate_track_height(panel_timeline->split_tracks.at(i), -1)); + p.drawLine(cursor_x, cursor_y, cursor_x, cursor_y + panel_timeline->GetTrackHeight(panel_timeline->split_tracks.at(i))); } } } @@ -2804,12 +2973,12 @@ void TimelineWidget::paintEvent(QPaintEvent*) { } // Draw edit cursor - if (isLiveEditing() && is_track_visible(panel_timeline->cursor_track)) { + if (current_tool_shows_cursor() && is_track_visible(panel_timeline->cursor_track)) { int cursor_x = panel_timeline->getTimelineScreenPointFromFrame(panel_timeline->cursor_frame); int cursor_y = getScreenPointFromTrack(panel_timeline->cursor_track); p.setPen(Qt::gray); - p.drawLine(cursor_x, cursor_y, cursor_x, cursor_y + panel_timeline->calculate_track_height(panel_timeline->cursor_track, -1)); + p.drawLine(cursor_x, cursor_y, cursor_x, cursor_y + panel_timeline->GetTrackHeight(panel_timeline->cursor_track)); } } } @@ -2827,38 +2996,62 @@ bool TimelineWidget::is_track_visible(int track) { // ************************************** int TimelineWidget::getTrackFromScreenPoint(int y) { + int track_candidate = 0; + y += scroll; + if (bottom_align) { - y = -(y - height()); + y -= height(); } - y--; - int height_measure = 0; - int counter = ((!bottom_align && y > 0) || (bottom_align && y < 0)) ? 0 : -1; - int track_height = panel_timeline->calculate_track_height(counter, -1); - while (qAbs(y) > height_measure+track_height) { - if (olive::CurrentConfig.show_track_lines && counter != -1) y--; - height_measure += track_height; - if ((!bottom_align && y > 0) || (bottom_align && y < 0)) { - counter++; + + if (y < 0) { + track_candidate--; + } + + int compounded_heights = 0; + + while (true) { + int track_height = panel_timeline->GetTrackHeight(track_candidate); + if (olive::CurrentConfig.show_track_lines) track_height++; + if (y < 0) { + track_height = -track_height; + } + + int next_compounded_height = compounded_heights + track_height; + + + if (y >= qMin(next_compounded_height, compounded_heights) && y < qMax(next_compounded_height, compounded_heights)) { + return track_candidate; + } + + compounded_heights = next_compounded_height; + + if (y < 0) { + track_candidate--; } else { - counter--; + track_candidate++; } - track_height = panel_timeline->calculate_track_height(counter, -1); } - return counter; } int TimelineWidget::getScreenPointFromTrack(int track) { - int y = 0; - int counter = 0; - while (counter != track) { - if (bottom_align) counter--; - y += panel_timeline->calculate_track_height(counter, -1); - if (!bottom_align) counter++; - if (olive::CurrentConfig.show_track_lines && counter != -1) y++; + int point = 0; + + int start = (track < 0) ? -1 : 0; + int interval = (track < 0) ? -1 : 1; + + if (track < 0) track--; + + for (int i=start;i!=track;i+=interval) { + point += panel_timeline->GetTrackHeight(i); + if (olive::CurrentConfig.show_track_lines) point++; + } + + if (bottom_align) { + return height() - point - scroll; + } else { + return point - scroll; } - y++; - return (bottom_align) ? height() - y - scroll : y - scroll; } int TimelineWidget::getClipIndexFromCoords(long frame, int track) { diff --git a/ui/timelinewidget.h b/ui/timelinewidget.h index 9a25a88dc..3e7481618 100644 --- a/ui/timelinewidget.h +++ b/ui/timelinewidget.h @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include "project/sequence.h" #include "project/clip.h" @@ -36,79 +38,86 @@ class Timeline; namespace olive { - namespace timeline { - const int kGhostThickness = 2; - const int kClipTextPadding = 3; + namespace timeline { + const int kGhostThickness = 2; + const int kClipTextPadding = 3; - const int kTrackMinHeight = 30; - const int kTrackHeightIncrement = 10; - } + const int kTrackDefaultHeight = 40/* * QApplication::desktop()->devicePixelRatio()*/; + const int kTrackMinHeight = 30; + const int kTrackHeightIncrement = 10; + } } +struct TimelineTrackHeight { + int index; + int height; +}; + bool same_sign(int a, int b); void draw_waveform(ClipPtr clip, const FootageStream *ms, long media_length, QPainter* p, const QRect& clip_rect, int waveform_start, int waveform_limit, double zoom); class TimelineWidget : public QWidget { - Q_OBJECT + Q_OBJECT public: - explicit TimelineWidget(QWidget *parent = 0); - QScrollBar* scrollBar; - bool bottom_align; + explicit TimelineWidget(QWidget *parent = 0); + QScrollBar* scrollBar; + bool bottom_align; + +public slots: + protected: - void paintEvent(QPaintEvent*); + void paintEvent(QPaintEvent*); - void resizeEvent(QResizeEvent *event); + void resizeEvent(QResizeEvent *event); - void mouseDoubleClickEvent(QMouseEvent *event); - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void leaveEvent(QEvent *event); + void mouseDoubleClickEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void leaveEvent(QEvent *event); - void dragEnterEvent(QDragEnterEvent *event); - void dragLeaveEvent(QDragLeaveEvent *event); - void dropEvent(QDropEvent* event); - void dragMoveEvent(QDragMoveEvent *event); + void dragEnterEvent(QDragEnterEvent *event); + void dragLeaveEvent(QDragLeaveEvent *event); + void dropEvent(QDropEvent* event); + void dragMoveEvent(QDragMoveEvent *event); - void wheelEvent(QWheelEvent *event); + void wheelEvent(QWheelEvent *event); private: - void init_ghosts(); - void update_ghosts(const QPoint& mouse_pos, bool lock_frame); - bool is_track_visible(int track); - int getTrackFromScreenPoint(int y); - int getScreenPointFromTrack(int track); - int getClipIndexFromCoords(long frame, int track); + void init_ghosts(); + void update_ghosts(const QPoint& mouse_pos, bool lock_frame); + bool is_track_visible(int track); + int getTrackFromScreenPoint(int y); + int getScreenPointFromTrack(int track); + int getClipIndexFromCoords(long frame, int track); - int track_resize_mouse_cache; - int track_resize_old_value; - bool track_resizing; - int track_target; + bool track_resizing; + int track_target; - QVector pre_clips; - QVector post_clips; + QVector pre_clips; + QVector post_clips; - Media* rc_reveal_media; + Media* rc_reveal_media; - SequencePtr self_created_sequence; + SequencePtr self_created_sequence; - QTimer tooltip_timer; - int tooltip_clip; + QTimer tooltip_timer; + int tooltip_clip; - int scroll; + int scroll; - SetSelectionsCommand* selection_command; + SetSelectionsCommand* selection_command; signals: public slots: - void setScroll(int); + void setScroll(int); private slots: - void reveal_media(); - void show_context_menu(const QPoint& pos); - void toggle_autoscale(); - void tooltip_timer_timeout(); - void rename_clip(); - void open_sequence_properties(); + void reveal_media(); + void show_context_menu(const QPoint& pos); + void toggle_autoscale(); + void tooltip_timer_timeout(); + void rename_clip(); + void open_sequence_properties(); }; #endif // TIMELINEWIDGET_H