diff --git a/dialogs/preferencesdialog.cpp b/dialogs/preferencesdialog.cpp index d2928032d..c3f711e69 100644 --- a/dialogs/preferencesdialog.cpp +++ b/dialogs/preferencesdialog.cpp @@ -51,666 +51,677 @@ #include KeySequenceEditor::KeySequenceEditor(QWidget* parent, QAction* a) - : QKeySequenceEdit(parent), action(a) { - setKeySequence(action->shortcut()); - //connect(this, SIGNAL(editingFinished()), this, SLOT(set_action_shortcut())); + : QKeySequenceEdit(parent), action(a) { + setKeySequence(action->shortcut()); + //connect(this, SIGNAL(editingFinished()), this, SLOT(set_action_shortcut())); } void KeySequenceEditor::set_action_shortcut() { - action->setShortcut(keySequence()); - action->setShortcutContext(Qt::ApplicationShortcut); + action->setShortcut(keySequence()); + action->setShortcutContext(Qt::ApplicationShortcut); } void KeySequenceEditor::reset_to_default() { - setKeySequence(action->property("default").toString()); + setKeySequence(action->property("default").toString()); } QString KeySequenceEditor::action_name() { - return action->property("id").toString(); + return action->property("id").toString(); } QString KeySequenceEditor::export_shortcut() { - QString ks = keySequence().toString(); - if (ks != action->property("default")) { - return action->property("id").toString() + "\t" + keySequence().toString(); - } - return 0; + QString ks = keySequence().toString(); + if (ks != action->property("default")) { + return action->property("id").toString() + "\t" + keySequence().toString(); + } + return 0; } PreferencesDialog::PreferencesDialog(QWidget *parent) : - QDialog(parent) + QDialog(parent) { - setWindowTitle(tr("Preferences")); - setup_ui(); + setWindowTitle(tr("Preferences")); + setup_ui(); - accurateSeekButton->setChecked(!olive::CurrentConfig.fast_seeking); - fastSeekButton->setChecked(olive::CurrentConfig.fast_seeking); - recordingComboBox->setCurrentIndex(olive::CurrentConfig.recording_mode - 1); - imgSeqFormatEdit->setText(olive::CurrentConfig.img_seq_formats); + accurateSeekButton->setChecked(!olive::CurrentConfig.fast_seeking); + fastSeekButton->setChecked(olive::CurrentConfig.fast_seeking); + recordingComboBox->setCurrentIndex(olive::CurrentConfig.recording_mode - 1); + imgSeqFormatEdit->setText(olive::CurrentConfig.img_seq_formats); } PreferencesDialog::~PreferencesDialog() {} void PreferencesDialog::setup_kbd_shortcut_worker(QMenu* menu, QTreeWidgetItem* parent) { - QList actions = menu->actions(); - for (int i=0;i actions = menu->actions(); + for (int i=0;iisSeparator() && a->property("keyignore").isNull()) { - QTreeWidgetItem* item = new QTreeWidgetItem(parent); - item->setText(0, a->text().replace("&", "")); + if (!a->isSeparator() && a->property("keyignore").isNull()) { + QTreeWidgetItem* item = new QTreeWidgetItem(parent); + item->setText(0, a->text().replace("&", "")); - parent->addChild(item); + parent->addChild(item); - if (a->menu() != nullptr) { - item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator); - setup_kbd_shortcut_worker(a->menu(), item); - } else { - key_shortcut_items.append(item); - key_shortcut_actions.append(a); - } - } + if (a->menu() != nullptr) { + item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator); + setup_kbd_shortcut_worker(a->menu(), item); + } else { + key_shortcut_items.append(item); + key_shortcut_actions.append(a); + } } + } } void PreferencesDialog::delete_previews(char type) { - if (type != 't' && type != 'w' && type != 1) return; + if (type != 't' && type != 'w' && type != 1) return; - QDir preview_path(get_data_path() + "/previews"); + QDir preview_path(get_data_path() + "/previews"); - if (type == 1) { - // indiscriminately delete everything - preview_path.removeRecursively(); - } else { - QStringList preview_file_list = preview_path.entryList(QDir::Files | QDir::NoDotAndDotDot); - for (int i=0;i= 0 - && preview_file_str.at(identifier_char_index) >= 48 - && preview_file_str.at(identifier_char_index) <= 57) { - identifier_char_index--; - } + // find identifier char + while (identifier_char_index >= 0 + && preview_file_str.at(identifier_char_index) >= 48 + && preview_file_str.at(identifier_char_index) <= 57) { + identifier_char_index--; + } - // thumbnails will have a 't' towards the end of the filenames, waveforms will have a 'w' - // if they match the type of preview we're deleting, remove them - if (preview_file_str.at(identifier_char_index) == type) { - QFile::remove(preview_path.filePath(preview_file_str)); - } - } + // thumbnails will have a 't' towards the end of the filenames, waveforms will have a 'w' + // if they match the type of preview we're deleting, remove them + if (preview_file_str.at(identifier_char_index) == type) { + QFile::remove(preview_path.filePath(preview_file_str)); + } } + } } void PreferencesDialog::setup_kbd_shortcuts(QMenuBar* menubar) { - QList menus = menubar->actions(); + QList menus = menubar->actions(); - for (int i=0;imenu(); + for (int i=0;imenu(); - QTreeWidgetItem* item = new QTreeWidgetItem(keyboard_tree); - item->setText(0, menu->title().replace("&", "")); + QTreeWidgetItem* item = new QTreeWidgetItem(keyboard_tree); + item->setText(0, menu->title().replace("&", "")); - keyboard_tree->addTopLevelItem(item); + keyboard_tree->addTopLevelItem(item); - setup_kbd_shortcut_worker(menu, item); - } + setup_kbd_shortcut_worker(menu, item); + } - for (int i=0;iproperty("id").isNull()) { - KeySequenceEditor* editor = new KeySequenceEditor(keyboard_tree, key_shortcut_actions.at(i)); - keyboard_tree->setItemWidget(key_shortcut_items.at(i), 1, editor); - key_shortcut_fields.append(editor); - } - } + for (int i=0;iproperty("id").isNull()) { + KeySequenceEditor* editor = new KeySequenceEditor(keyboard_tree, key_shortcut_actions.at(i)); + keyboard_tree->setItemWidget(key_shortcut_items.at(i), 1, editor); + key_shortcut_fields.append(editor); + } + } } void PreferencesDialog::save() { - bool restart_after_saving = false; - bool reinit_audio = false; + bool restart_after_saving = false; + bool reinit_audio = false; + bool reload_language = false; - // Validate whether the specified CSS file exists - if (!custom_css_fn->text().isEmpty() && !QFileInfo::exists(custom_css_fn->text())) { - QMessageBox::critical( - this, - tr("Invalid CSS File"), - tr("CSS file '%1' does not exist.").arg(custom_css_fn->text()) - ); - return; - } + // Validate whether the specified CSS file exists + if (!custom_css_fn->text().isEmpty() && !QFileInfo::exists(custom_css_fn->text())) { + QMessageBox::critical( + this, + tr("Invalid CSS File"), + tr("CSS file '%1' does not exist.").arg(custom_css_fn->text()) + ); + return; + } - // Check if any settings will require a restart of Olive - if (olive::CurrentConfig.effect_textbox_lines != effect_textbox_lines_field->value() - || olive::CurrentConfig.use_software_fallback != use_software_fallbacks_checkbox->isChecked() - || olive::CurrentConfig.language_file != language_combobox->currentData().toString() - || olive::CurrentConfig.thumbnail_resolution != thumbnail_res_spinbox->value() - || olive::CurrentConfig.waveform_resolution != waveform_res_spinbox->value()) { + // Check if any settings will require a restart of Olive + if (olive::CurrentConfig.effect_textbox_lines != effect_textbox_lines_field->value() + || olive::CurrentConfig.use_software_fallback != use_software_fallbacks_checkbox->isChecked() + || olive::CurrentConfig.thumbnail_resolution != thumbnail_res_spinbox->value() + || olive::CurrentConfig.waveform_resolution != waveform_res_spinbox->value()) { - // any changes to these settings will require a restart - ask the user if we should do one now or later + // any changes to these settings will require a restart - ask the user if we should do one now or later - int ret = QMessageBox::question(this, - "Restart Required", - "Some of the changed settings will require a restart of Olive. Would you like " - "to restart now?", - QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + int ret = QMessageBox::question(this, + "Restart Required", + "Some of the changed settings will require a restart of Olive. Would you like " + "to restart now?", + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - if (ret == QMessageBox::Cancel) { - // Return to Preferences dialog without saving any settings - return; - } else if (ret == QMessageBox::Yes) { + if (ret == QMessageBox::Cancel) { + // Return to Preferences dialog without saving any settings + return; + } else if (ret == QMessageBox::Yes) { - // Check if we can close the current project. If not, we'll treat it as if the user clicked "Cancel". - if (olive::Global->can_close_project()) { - restart_after_saving = true; - } else { - return; - } - } - // Selecting "No" will save the settings and not restart. They will become active next time Olive opens. + // Check if we can close the current project. If not, we'll treat it as if the user clicked "Cancel". + if (olive::Global->can_close_project()) { + restart_after_saving = true; + } else { + return; + } + } + // Selecting "No" will save the settings and not restart. They will become active next time Olive opens. + } + + // Audio settings may require the audio device to be re-initiated. + if (olive::CurrentConfig.preferred_audio_output != audio_output_devices->currentData().toString() + || olive::CurrentConfig.preferred_audio_input != audio_input_devices->currentData().toString() + || olive::CurrentConfig.audio_rate != audio_sample_rate->currentData().toInt()) { + reinit_audio = true; + } + + // see if the language file should be reloaded (not necessary if the app is restarting anyway) + if (!restart_after_saving + && olive::CurrentConfig.language_file != language_combobox->currentData().toString()) { + reload_language = true; + } + + // save settings from UI to backend + olive::CurrentConfig.css_path = custom_css_fn->text(); + olive::MainWindow->load_css_from_file(olive::CurrentConfig.css_path); + + olive::CurrentConfig.recording_mode = recordingComboBox->currentIndex() + 1; + olive::CurrentConfig.img_seq_formats = imgSeqFormatEdit->text(); + olive::CurrentConfig.fast_seeking = fastSeekButton->isChecked(); + olive::CurrentConfig.upcoming_queue_size = upcoming_queue_spinbox->value(); + olive::CurrentConfig.upcoming_queue_type = upcoming_queue_type->currentIndex(); + olive::CurrentConfig.previous_queue_size = previous_queue_spinbox->value(); + olive::CurrentConfig.previous_queue_type = previous_queue_type->currentIndex(); + olive::CurrentConfig.add_default_effects_to_clips = add_default_effects_to_clips->isChecked(); + + olive::CurrentConfig.preferred_audio_output = audio_output_devices->currentData().toString(); + olive::CurrentConfig.preferred_audio_input = audio_input_devices->currentData().toString(); + olive::CurrentConfig.audio_rate = audio_sample_rate->currentData().toInt(); + + olive::CurrentConfig.effect_textbox_lines = effect_textbox_lines_field->value(); + olive::CurrentConfig.use_software_fallback = use_software_fallbacks_checkbox->isChecked(); + olive::CurrentConfig.language_file = language_combobox->currentData().toString(); + + if (olive::CurrentConfig.thumbnail_resolution != thumbnail_res_spinbox->value() + || olive::CurrentConfig.waveform_resolution != waveform_res_spinbox->value()) { + // we're changing the size of thumbnails and waveforms, so let's delete them and regenerate them next start + + // delete nothing + char delete_match = 0; + + if (olive::CurrentConfig.thumbnail_resolution != thumbnail_res_spinbox->value()) { + // delete existing thumbnails + olive::CurrentConfig.thumbnail_resolution = thumbnail_res_spinbox->value(); + + // delete only thumbnails + delete_match = 't'; } - // Audio settings may require the audio device to be re-initiated. - if (olive::CurrentConfig.preferred_audio_output != audio_output_devices->currentData().toString() - || olive::CurrentConfig.preferred_audio_input != audio_input_devices->currentData().toString() - || olive::CurrentConfig.audio_rate != audio_sample_rate->currentData().toInt()) { - reinit_audio = true; + if (olive::CurrentConfig.waveform_resolution != waveform_res_spinbox->value()) { + // delete existing waveforms + olive::CurrentConfig.waveform_resolution = waveform_res_spinbox->value(); + + // if we're already deleting thumbnails + if (delete_match == 't') { + // delete all + delete_match = 1; + } else { + // just delete waveforms + delete_match = 'w'; + } } - // save settings from UI to backend - olive::CurrentConfig.css_path = custom_css_fn->text(); - olive::MainWindow->load_css_from_file(olive::CurrentConfig.css_path); + delete_previews(delete_match); + } - olive::CurrentConfig.recording_mode = recordingComboBox->currentIndex() + 1; - olive::CurrentConfig.img_seq_formats = imgSeqFormatEdit->text(); - olive::CurrentConfig.fast_seeking = fastSeekButton->isChecked(); - olive::CurrentConfig.upcoming_queue_size = upcoming_queue_spinbox->value(); - olive::CurrentConfig.upcoming_queue_type = upcoming_queue_type->currentIndex(); - olive::CurrentConfig.previous_queue_size = previous_queue_spinbox->value(); - olive::CurrentConfig.previous_queue_type = previous_queue_type->currentIndex(); - olive::CurrentConfig.add_default_effects_to_clips = add_default_effects_to_clips->isChecked(); + // Save keyboard shortcuts + for (int i=0;iset_action_shortcut(); + } - olive::CurrentConfig.preferred_audio_output = audio_output_devices->currentData().toString(); - olive::CurrentConfig.preferred_audio_input = audio_input_devices->currentData().toString(); - olive::CurrentConfig.audio_rate = audio_sample_rate->currentData().toInt(); + // Audio settings may require the audio device to be re-initiated. + if (reinit_audio) { + init_audio(); + } - olive::CurrentConfig.effect_textbox_lines = effect_textbox_lines_field->value(); - olive::CurrentConfig.use_software_fallback = use_software_fallbacks_checkbox->isChecked(); - olive::CurrentConfig.language_file = language_combobox->currentData().toString(); + // reload language file if it changed + if (reload_language) { + olive::Global->load_translation_from_config(); + } - if (olive::CurrentConfig.thumbnail_resolution != thumbnail_res_spinbox->value() - || olive::CurrentConfig.waveform_resolution != waveform_res_spinbox->value()) { - // we're changing the size of thumbnails and waveforms, so let's delete them and regenerate them next start + accept(); - // delete nothing - char delete_match = 0; + if (restart_after_saving) { + // since we already ran can_close_project(), bypass checking again by running setWindowModified(false) + olive::MainWindow->setWindowModified(false); - if (olive::CurrentConfig.thumbnail_resolution != thumbnail_res_spinbox->value()) { - // delete existing thumbnails - olive::CurrentConfig.thumbnail_resolution = thumbnail_res_spinbox->value(); + olive::MainWindow->close(); - // delete only thumbnails - delete_match = 't'; - } - - if (olive::CurrentConfig.waveform_resolution != waveform_res_spinbox->value()) { - // delete existing waveforms - olive::CurrentConfig.waveform_resolution = waveform_res_spinbox->value(); - - // if we're already deleting thumbnails - if (delete_match == 't') { - // delete all - delete_match = 1; - } else { - // just delete waveforms - delete_match = 'w'; - } - } - - delete_previews(delete_match); - } - - // Save keyboard shortcuts - for (int i=0;iset_action_shortcut(); - } - - // Audio settings may require the audio device to be re-initiated. - if (reinit_audio) { - init_audio(); - } - - accept(); - - if (restart_after_saving) { - // since we already ran can_close_project(), bypass checking again by running setWindowModified(false) - olive::MainWindow->setWindowModified(false); - - olive::MainWindow->close(); - - QProcess::startDetached(QApplication::applicationFilePath(), { olive::ActiveProjectFilename }); - } + QProcess::startDetached(QApplication::applicationFilePath(), { olive::ActiveProjectFilename }); + } } void PreferencesDialog::reset_default_shortcut() { - QList items = keyboard_tree->selectedItems(); - for (int i=0;iselectedItems().at(i); - static_cast(keyboard_tree->itemWidget(item, 1))->reset_to_default(); - } + QList items = keyboard_tree->selectedItems(); + for (int i=0;iselectedItems().at(i); + static_cast(keyboard_tree->itemWidget(item, 1))->reset_to_default(); + } } void PreferencesDialog::reset_all_shortcuts() { - if (QMessageBox::question( - this, - tr("Confirm Reset All Shortcuts"), - tr("Are you sure you wish to reset all keyboard shortcuts to their defaults?"), - QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { - for (int i=0;ireset_to_default(); - } - } + if (QMessageBox::question( + this, + tr("Confirm Reset All Shortcuts"), + tr("Are you sure you wish to reset all keyboard shortcuts to their defaults?"), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + for (int i=0;ireset_to_default(); + } + } } bool PreferencesDialog::refine_shortcut_list(const QString &s, QTreeWidgetItem* parent) { - if (parent == nullptr) { - for (int i=0;itopLevelItemCount();i++) { - refine_shortcut_list(s, keyboard_tree->topLevelItem(i)); - } - } else { - parent->setExpanded(!s.isEmpty()); + if (parent == nullptr) { + for (int i=0;itopLevelItemCount();i++) { + refine_shortcut_list(s, keyboard_tree->topLevelItem(i)); + } + } else { + parent->setExpanded(!s.isEmpty()); - bool all_children_are_hidden = !s.isEmpty(); + bool all_children_are_hidden = !s.isEmpty(); - for (int i=0;ichildCount();i++) { - QTreeWidgetItem* item = parent->child(i); - if (item->childCount() > 0) { - all_children_are_hidden = refine_shortcut_list(s, item); - } else { - item->setHidden(false); - if (s.isEmpty()) { - all_children_are_hidden = false; - } else { - QString shortcut; - if (keyboard_tree->itemWidget(item, 1) != nullptr) { - shortcut = static_cast(keyboard_tree->itemWidget(item, 1))->keySequence().toString(); - } - if (item->text(0).contains(s, Qt::CaseInsensitive) || shortcut.contains(s, Qt::CaseInsensitive)) { - all_children_are_hidden = false; - } else { - item->setHidden(true); - } - } - } - } + for (int i=0;ichildCount();i++) { + QTreeWidgetItem* item = parent->child(i); + if (item->childCount() > 0) { + all_children_are_hidden = refine_shortcut_list(s, item); + } else { + item->setHidden(false); + if (s.isEmpty()) { + all_children_are_hidden = false; + } else { + QString shortcut; + if (keyboard_tree->itemWidget(item, 1) != nullptr) { + shortcut = static_cast(keyboard_tree->itemWidget(item, 1))->keySequence().toString(); + } + if (item->text(0).contains(s, Qt::CaseInsensitive) || shortcut.contains(s, Qt::CaseInsensitive)) { + all_children_are_hidden = false; + } else { + item->setHidden(true); + } + } + } + } - if (parent->text(0).contains(s, Qt::CaseInsensitive)) all_children_are_hidden = false; + if (parent->text(0).contains(s, Qt::CaseInsensitive)) all_children_are_hidden = false; - parent->setHidden(all_children_are_hidden); + parent->setHidden(all_children_are_hidden); - return all_children_are_hidden; - } - return true; + return all_children_are_hidden; + } + return true; } void PreferencesDialog::load_shortcut_file() { - QString fn = QFileDialog::getOpenFileName(this, tr("Import Keyboard Shortcuts")); - if (!fn.isEmpty()) { - QFile f(fn); - if (f.exists() && f.open(QFile::ReadOnly)) { - QByteArray ba = f.readAll(); - f.close(); - for (int i=0;iaction_name()); - if (index == 0 || (index > 0 && ba.at(index-1) == '\n')) { - while (index < ba.size() && ba.at(index) != '\t') index++; - QString ks; - index++; - while (index < ba.size() && ba.at(index) != '\n') { - ks.append(ba.at(index)); - index++; - } - key_shortcut_fields.at(i)->setKeySequence(ks); - } else { - key_shortcut_fields.at(i)->reset_to_default(); - } - } - } else { - QMessageBox::critical( - this, - tr("Error saving shortcuts"), - tr("Failed to open file for reading") - ); - } - } + QString fn = QFileDialog::getOpenFileName(this, tr("Import Keyboard Shortcuts")); + if (!fn.isEmpty()) { + QFile f(fn); + if (f.exists() && f.open(QFile::ReadOnly)) { + QByteArray ba = f.readAll(); + f.close(); + for (int i=0;iaction_name()); + if (index == 0 || (index > 0 && ba.at(index-1) == '\n')) { + while (index < ba.size() && ba.at(index) != '\t') index++; + QString ks; + index++; + while (index < ba.size() && ba.at(index) != '\n') { + ks.append(ba.at(index)); + index++; + } + key_shortcut_fields.at(i)->setKeySequence(ks); + } else { + key_shortcut_fields.at(i)->reset_to_default(); + } + } + } else { + QMessageBox::critical( + this, + tr("Error saving shortcuts"), + tr("Failed to open file for reading") + ); + } + } } void PreferencesDialog::save_shortcut_file() { - QString fn = QFileDialog::getSaveFileName(this, tr("Export Keyboard Shortcuts")); - if (!fn.isEmpty()) { - QFile f(fn); - if (f.open(QFile::WriteOnly)) { - bool start = true; - for (int i=0;iexport_shortcut(); - if (!s.isEmpty()) { - if (!start) f.write("\n"); - f.write(s.toUtf8()); - start = false; - } - } - f.close(); - QMessageBox::information(this, tr("Export Shortcuts"), tr("Shortcuts exported successfully")); - } else { - QMessageBox::critical(this, tr("Error saving shortcuts"), tr("Failed to open file for writing")); - } - } + QString fn = QFileDialog::getSaveFileName(this, tr("Export Keyboard Shortcuts")); + if (!fn.isEmpty()) { + QFile f(fn); + if (f.open(QFile::WriteOnly)) { + bool start = true; + for (int i=0;iexport_shortcut(); + if (!s.isEmpty()) { + if (!start) f.write("\n"); + f.write(s.toUtf8()); + start = false; + } + } + f.close(); + QMessageBox::information(this, tr("Export Shortcuts"), tr("Shortcuts exported successfully")); + } else { + QMessageBox::critical(this, tr("Error saving shortcuts"), tr("Failed to open file for writing")); + } + } } void PreferencesDialog::browse_css_file() { - QString fn = QFileDialog::getOpenFileName(this, tr("Browse for CSS file")); - if (!fn.isEmpty()) { - custom_css_fn->setText(fn); - } + QString fn = QFileDialog::getOpenFileName(this, tr("Browse for CSS file")); + if (!fn.isEmpty()) { + custom_css_fn->setText(fn); + } } void PreferencesDialog::delete_all_previews() { - if (QMessageBox::question(this, - tr("Delete All Previews"), - tr("Are you sure you want to delete all previews?"), - QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { - delete_previews(1); - QMessageBox::information(this, - tr("Previews Deleted"), - tr("All previews deleted succesfully. You may have to re-open your current project for changes to take effect."), - QMessageBox::Ok); - } + if (QMessageBox::question(this, + tr("Delete All Previews"), + tr("Are you sure you want to delete all previews?"), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + delete_previews(1); + QMessageBox::information(this, + tr("Previews Deleted"), + tr("All previews deleted succesfully. You may have to re-open your current project for changes to take effect."), + QMessageBox::Ok); + } } void PreferencesDialog::setup_ui() { - QVBoxLayout* verticalLayout = new QVBoxLayout(this); - QTabWidget* tabWidget = new QTabWidget(this); + QVBoxLayout* verticalLayout = new QVBoxLayout(this); + QTabWidget* tabWidget = new QTabWidget(this); - // row counter used to ease adding new rows - int row = 0; + // row counter used to ease adding new rows + int row = 0; - // General - QWidget* general_tab = new QWidget(this); - QGridLayout* general_layout = new QGridLayout(general_tab); + // General + QWidget* general_tab = new QWidget(this); + QGridLayout* general_layout = new QGridLayout(general_tab); - // General -> Language - general_layout->addWidget(new QLabel(tr("Language:")), row, 0); + // General -> Language + general_layout->addWidget(new QLabel(tr("Language:")), row, 0); - language_combobox = new QComboBox(); + language_combobox = new QComboBox(); - // add default language (en-US) - language_combobox->addItem(QLocale::languageToString(QLocale("en-US").language())); + // add default language (en-US) + language_combobox->addItem(QLocale::languageToString(QLocale("en-US").language())); - // add languages from file - QList translation_paths = get_language_paths(); + // add languages from file + QList translation_paths = get_language_paths(); - // iterate through all language search paths - for (int j=0;jaddItem(QLocale(locale_str).nativeLanguageName(), locale_relative_path); + QFileInfo locale_file(translation_files.at(i)); + QString locale_file_basename = locale_file.baseName(); + QString locale_str = locale_file_basename.mid(locale_file_basename.lastIndexOf('_')+1); + language_combobox->addItem(QLocale(locale_str).nativeLanguageName(), locale_relative_path); - if (olive::CurrentConfig.language_file == locale_relative_path) { - language_combobox->setCurrentIndex(language_combobox->count() - 1); - } - } - } - } + if (olive::CurrentConfig.language_file == locale_relative_path) { + language_combobox->setCurrentIndex(language_combobox->count() - 1); + } + } + } + } - general_layout->addWidget(language_combobox, row, 1, 1, 4); + general_layout->addWidget(language_combobox, row, 1, 1, 4); - row++; + row++; - // General -> Custom CSS - general_layout->addWidget(new QLabel(tr("Custom CSS:"), this), row, 0); + // General -> Custom CSS + general_layout->addWidget(new QLabel(tr("Custom CSS:"), this), row, 0); - custom_css_fn = new QLineEdit(general_tab); - custom_css_fn->setText(olive::CurrentConfig.css_path); - general_layout->addWidget(custom_css_fn, row, 1, 1, 3); + custom_css_fn = new QLineEdit(general_tab); + custom_css_fn->setText(olive::CurrentConfig.css_path); + general_layout->addWidget(custom_css_fn, row, 1, 1, 3); - QPushButton* custom_css_browse = new QPushButton(tr("Browse"), general_tab); - connect(custom_css_browse, SIGNAL(clicked(bool)), this, SLOT(browse_css_file())); - general_layout->addWidget(custom_css_browse, row, 4); + QPushButton* custom_css_browse = new QPushButton(tr("Browse"), general_tab); + connect(custom_css_browse, SIGNAL(clicked(bool)), this, SLOT(browse_css_file())); + general_layout->addWidget(custom_css_browse, row, 4); - row++; - - // General -> Image Sequence Formats - general_layout->addWidget(new QLabel(tr("Image sequence formats:"), this), row, 0); - - imgSeqFormatEdit = new QLineEdit(general_tab); - - general_layout->addWidget(imgSeqFormatEdit, row, 1, 1, 4); - - row++; - - // General -> Audio Recording - general_layout->addWidget(new QLabel(tr("Audio Recording:"), this), row, 0); - - recordingComboBox = new QComboBox(general_tab); - recordingComboBox->addItem(tr("Mono")); - recordingComboBox->addItem(tr("Stereo")); - general_layout->addWidget(recordingComboBox, row, 1, 1, 4); - - row++; + row++; + + // General -> Image Sequence Formats + general_layout->addWidget(new QLabel(tr("Image sequence formats:"), this), row, 0); + + imgSeqFormatEdit = new QLineEdit(general_tab); + + general_layout->addWidget(imgSeqFormatEdit, row, 1, 1, 4); + + row++; + + // General -> Audio Recording + general_layout->addWidget(new QLabel(tr("Audio Recording:"), this), row, 0); + + recordingComboBox = new QComboBox(general_tab); + recordingComboBox->addItem(tr("Mono")); + recordingComboBox->addItem(tr("Stereo")); + general_layout->addWidget(recordingComboBox, row, 1, 1, 4); + + row++; - // General -> Effect Textbox Lines - general_layout->addWidget(new QLabel(tr("Effect Textbox Lines:"), this), row, 0); + // General -> Effect Textbox Lines + general_layout->addWidget(new QLabel(tr("Effect Textbox Lines:"), this), row, 0); - effect_textbox_lines_field = new QSpinBox(general_tab); - effect_textbox_lines_field->setMinimum(1); - effect_textbox_lines_field->setValue(olive::CurrentConfig.effect_textbox_lines); - general_layout->addWidget(effect_textbox_lines_field, row, 1, 1, 4); - - row++; - - // General -> Thumbnail and Waveform Resolution - general_layout->addWidget(new QLabel(tr("Thumbnail Resolution:"), this), row, 0); - - thumbnail_res_spinbox = new QSpinBox(this); - thumbnail_res_spinbox->setMinimum(0); - thumbnail_res_spinbox->setMaximum(INT_MAX); - thumbnail_res_spinbox->setValue(olive::CurrentConfig.thumbnail_resolution); - general_layout->addWidget(thumbnail_res_spinbox, row, 1); - - general_layout->addWidget(new QLabel(tr("Waveform Resolution:"), this), row, 2); - - waveform_res_spinbox = new QSpinBox(this); - waveform_res_spinbox->setMinimum(0); - waveform_res_spinbox->setMaximum(INT_MAX); - waveform_res_spinbox->setValue(olive::CurrentConfig.waveform_resolution); - general_layout->addWidget(waveform_res_spinbox, row, 3); - - QPushButton* delete_preview_btn = new QPushButton(tr("Delete Previews")); - general_layout->addWidget(delete_preview_btn, row, 4); - connect(delete_preview_btn, SIGNAL(clicked(bool)), this, SLOT(delete_all_previews())); - - row++; - - // General -> Use Software Fallbacks When Possible - use_software_fallbacks_checkbox = new QCheckBox(general_tab); - use_software_fallbacks_checkbox->setText(tr("Use Software Fallbacks When Possible")); - use_software_fallbacks_checkbox->setChecked(olive::CurrentConfig.use_software_fallback); - general_layout->addWidget(use_software_fallbacks_checkbox, row, 0, 1, 4); - - tabWidget->addTab(general_tab, tr("General")); - - // Behavior - QWidget* behavior_tab = new QWidget(this); - tabWidget->addTab(behavior_tab, tr("Behavior")); - - QVBoxLayout* behavior_tab_layout = new QVBoxLayout(behavior_tab); - - add_default_effects_to_clips = new QCheckBox("Add Default Effects to New Clips"); - add_default_effects_to_clips->setChecked(olive::CurrentConfig.add_default_effects_to_clips); - behavior_tab_layout->addWidget(add_default_effects_to_clips); - - // Playback - QWidget* playback_tab = new QWidget(this); - QVBoxLayout* playback_tab_layout = new QVBoxLayout(playback_tab); - - // Playback -> Seeking - QGroupBox* seeking_group = new QGroupBox(playback_tab); - seeking_group->setTitle(tr("Seeking")); - QVBoxLayout* seeking_group_layout = new QVBoxLayout(seeking_group); - accurateSeekButton = new QRadioButton(seeking_group); - accurateSeekButton->setText(tr("Accurate Seeking\nAlways show the correct frame (visual may pause briefly as correct frame is retrieved)")); - seeking_group_layout->addWidget(accurateSeekButton); - fastSeekButton = new QRadioButton(seeking_group); - fastSeekButton->setText(tr("Fast Seeking\nSeek quickly (may briefly show inaccurate frames when seeking - doesn't affect playback/export)")); - seeking_group_layout->addWidget(fastSeekButton); - playback_tab_layout->addWidget(seeking_group); - - // Playback -> Memory Usage - QGroupBox* memory_usage_group = new QGroupBox(playback_tab); - memory_usage_group->setTitle(tr("Memory Usage")); - QGridLayout* memory_usage_layout = new QGridLayout(memory_usage_group); - memory_usage_layout->addWidget(new QLabel(tr("Upcoming Frame Queue:"), playback_tab), 0, 0); - upcoming_queue_spinbox = new QDoubleSpinBox(playback_tab); - upcoming_queue_spinbox->setValue(olive::CurrentConfig.upcoming_queue_size); - memory_usage_layout->addWidget(upcoming_queue_spinbox, 0, 1); - upcoming_queue_type = new QComboBox(playback_tab); - upcoming_queue_type->addItem(tr("frames")); - upcoming_queue_type->addItem(tr("seconds")); - upcoming_queue_type->setCurrentIndex(olive::CurrentConfig.upcoming_queue_type); - memory_usage_layout->addWidget(upcoming_queue_type, 0, 2); - memory_usage_layout->addWidget(new QLabel(tr("Previous Frame Queue:"), playback_tab), 1, 0); - previous_queue_spinbox = new QDoubleSpinBox(playback_tab); - previous_queue_spinbox->setValue(olive::CurrentConfig.previous_queue_size); - memory_usage_layout->addWidget(previous_queue_spinbox, 1, 1); - previous_queue_type = new QComboBox(playback_tab); - previous_queue_type->addItem(tr("frames")); - previous_queue_type->addItem(tr("seconds")); - previous_queue_type->setCurrentIndex(olive::CurrentConfig.previous_queue_type); - memory_usage_layout->addWidget(previous_queue_type, 1, 2); - playback_tab_layout->addWidget(memory_usage_group); - - tabWidget->addTab(playback_tab, tr("Playback")); - - // Audio - QWidget* audio_tab = new QWidget(this); - - QGridLayout* audio_tab_layout = new QGridLayout(audio_tab); - - audio_tab_layout->addWidget(new QLabel(tr("Output Device:")), 0, 0); - - audio_output_devices = new QComboBox(); - audio_output_devices->addItem(tr("Default"), ""); - - // list all available audio output devices - QList devs = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput); - bool found_preferred_device = false; - for (int i=0;iaddItem(devs.at(i).deviceName(), devs.at(i).deviceName()); - if (!found_preferred_device - && devs.at(i).deviceName() == olive::CurrentConfig.preferred_audio_output) { - audio_output_devices->setCurrentIndex(audio_output_devices->count()-1); - found_preferred_device = true; - } - } - - audio_tab_layout->addWidget(audio_output_devices, 0, 1); - - audio_tab_layout->addWidget(new QLabel(tr("Input Device:")), 1, 0); - - audio_input_devices = new QComboBox(); - audio_input_devices->addItem(tr("Default"), ""); - - // list all available audio input devices - devs = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); - found_preferred_device = false; - for (int i=0;iaddItem(devs.at(i).deviceName(), devs.at(i).deviceName()); - if (!found_preferred_device - && devs.at(i).deviceName() == olive::CurrentConfig.preferred_audio_input) { - audio_input_devices->setCurrentIndex(audio_input_devices->count()-1); - found_preferred_device = true; - } - } - - audio_tab_layout->addWidget(audio_input_devices, 1, 1); - - audio_tab_layout->addWidget(new QLabel(tr("Sample Rate:")), 2, 0); - - audio_sample_rate = new QComboBox(); - combobox_audio_sample_rates(audio_sample_rate); - for (int i=0;icount();i++) { - if (audio_sample_rate->itemData(i).toInt() == olive::CurrentConfig.audio_rate) { - audio_sample_rate->setCurrentIndex(i); - break; - } - } - - audio_tab_layout->addWidget(audio_sample_rate, 2, 1); - - tabWidget->addTab(audio_tab, tr("Audio")); - - // Shortcuts - QWidget* shortcut_tab = new QWidget(this); - - QVBoxLayout* shortcut_layout = new QVBoxLayout(shortcut_tab); - - QLineEdit* key_search_line = new QLineEdit(shortcut_tab); - key_search_line->setPlaceholderText(tr("Search for action or shortcut")); - connect(key_search_line, SIGNAL(textChanged(const QString &)), this, SLOT(refine_shortcut_list(const QString &))); - - shortcut_layout->addWidget(key_search_line); - - keyboard_tree = new QTreeWidget(shortcut_tab); - QTreeWidgetItem* tree_header = keyboard_tree->headerItem(); - tree_header->setText(0, tr("Action")); - tree_header->setText(1, tr("Shortcut")); - shortcut_layout->addWidget(keyboard_tree); - - QHBoxLayout* reset_shortcut_layout = new QHBoxLayout(shortcut_tab); - - QPushButton* import_shortcut_button = new QPushButton(tr("Import"), shortcut_tab); - reset_shortcut_layout->addWidget(import_shortcut_button); - connect(import_shortcut_button, SIGNAL(clicked(bool)), this, SLOT(load_shortcut_file())); + effect_textbox_lines_field = new QSpinBox(general_tab); + effect_textbox_lines_field->setMinimum(1); + effect_textbox_lines_field->setValue(olive::CurrentConfig.effect_textbox_lines); + general_layout->addWidget(effect_textbox_lines_field, row, 1, 1, 4); + + row++; + + // General -> Thumbnail and Waveform Resolution + general_layout->addWidget(new QLabel(tr("Thumbnail Resolution:"), this), row, 0); + + thumbnail_res_spinbox = new QSpinBox(this); + thumbnail_res_spinbox->setMinimum(0); + thumbnail_res_spinbox->setMaximum(INT_MAX); + thumbnail_res_spinbox->setValue(olive::CurrentConfig.thumbnail_resolution); + general_layout->addWidget(thumbnail_res_spinbox, row, 1); + + general_layout->addWidget(new QLabel(tr("Waveform Resolution:"), this), row, 2); + + waveform_res_spinbox = new QSpinBox(this); + waveform_res_spinbox->setMinimum(0); + waveform_res_spinbox->setMaximum(INT_MAX); + waveform_res_spinbox->setValue(olive::CurrentConfig.waveform_resolution); + general_layout->addWidget(waveform_res_spinbox, row, 3); + + QPushButton* delete_preview_btn = new QPushButton(tr("Delete Previews")); + general_layout->addWidget(delete_preview_btn, row, 4); + connect(delete_preview_btn, SIGNAL(clicked(bool)), this, SLOT(delete_all_previews())); + + row++; + + // General -> Use Software Fallbacks When Possible + use_software_fallbacks_checkbox = new QCheckBox(general_tab); + use_software_fallbacks_checkbox->setText(tr("Use Software Fallbacks When Possible")); + use_software_fallbacks_checkbox->setChecked(olive::CurrentConfig.use_software_fallback); + general_layout->addWidget(use_software_fallbacks_checkbox, row, 0, 1, 4); + + tabWidget->addTab(general_tab, tr("General")); + + // Behavior + QWidget* behavior_tab = new QWidget(this); + tabWidget->addTab(behavior_tab, tr("Behavior")); + + QVBoxLayout* behavior_tab_layout = new QVBoxLayout(behavior_tab); + + add_default_effects_to_clips = new QCheckBox("Add Default Effects to New Clips"); + add_default_effects_to_clips->setChecked(olive::CurrentConfig.add_default_effects_to_clips); + behavior_tab_layout->addWidget(add_default_effects_to_clips); + + // Playback + QWidget* playback_tab = new QWidget(this); + QVBoxLayout* playback_tab_layout = new QVBoxLayout(playback_tab); + + // Playback -> Seeking + QGroupBox* seeking_group = new QGroupBox(playback_tab); + seeking_group->setTitle(tr("Seeking")); + QVBoxLayout* seeking_group_layout = new QVBoxLayout(seeking_group); + accurateSeekButton = new QRadioButton(seeking_group); + accurateSeekButton->setText(tr("Accurate Seeking\nAlways show the correct frame (visual may pause briefly as correct frame is retrieved)")); + seeking_group_layout->addWidget(accurateSeekButton); + fastSeekButton = new QRadioButton(seeking_group); + fastSeekButton->setText(tr("Fast Seeking\nSeek quickly (may briefly show inaccurate frames when seeking - doesn't affect playback/export)")); + seeking_group_layout->addWidget(fastSeekButton); + playback_tab_layout->addWidget(seeking_group); + + // Playback -> Memory Usage + QGroupBox* memory_usage_group = new QGroupBox(playback_tab); + memory_usage_group->setTitle(tr("Memory Usage")); + QGridLayout* memory_usage_layout = new QGridLayout(memory_usage_group); + memory_usage_layout->addWidget(new QLabel(tr("Upcoming Frame Queue:"), playback_tab), 0, 0); + upcoming_queue_spinbox = new QDoubleSpinBox(playback_tab); + upcoming_queue_spinbox->setValue(olive::CurrentConfig.upcoming_queue_size); + memory_usage_layout->addWidget(upcoming_queue_spinbox, 0, 1); + upcoming_queue_type = new QComboBox(playback_tab); + upcoming_queue_type->addItem(tr("frames")); + upcoming_queue_type->addItem(tr("seconds")); + upcoming_queue_type->setCurrentIndex(olive::CurrentConfig.upcoming_queue_type); + memory_usage_layout->addWidget(upcoming_queue_type, 0, 2); + memory_usage_layout->addWidget(new QLabel(tr("Previous Frame Queue:"), playback_tab), 1, 0); + previous_queue_spinbox = new QDoubleSpinBox(playback_tab); + previous_queue_spinbox->setValue(olive::CurrentConfig.previous_queue_size); + memory_usage_layout->addWidget(previous_queue_spinbox, 1, 1); + previous_queue_type = new QComboBox(playback_tab); + previous_queue_type->addItem(tr("frames")); + previous_queue_type->addItem(tr("seconds")); + previous_queue_type->setCurrentIndex(olive::CurrentConfig.previous_queue_type); + memory_usage_layout->addWidget(previous_queue_type, 1, 2); + playback_tab_layout->addWidget(memory_usage_group); + + tabWidget->addTab(playback_tab, tr("Playback")); + + // Audio + QWidget* audio_tab = new QWidget(this); + + QGridLayout* audio_tab_layout = new QGridLayout(audio_tab); + + audio_tab_layout->addWidget(new QLabel(tr("Output Device:")), 0, 0); + + audio_output_devices = new QComboBox(); + audio_output_devices->addItem(tr("Default"), ""); + + // list all available audio output devices + QList devs = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput); + bool found_preferred_device = false; + for (int i=0;iaddItem(devs.at(i).deviceName(), devs.at(i).deviceName()); + if (!found_preferred_device + && devs.at(i).deviceName() == olive::CurrentConfig.preferred_audio_output) { + audio_output_devices->setCurrentIndex(audio_output_devices->count()-1); + found_preferred_device = true; + } + } + + audio_tab_layout->addWidget(audio_output_devices, 0, 1); + + audio_tab_layout->addWidget(new QLabel(tr("Input Device:")), 1, 0); + + audio_input_devices = new QComboBox(); + audio_input_devices->addItem(tr("Default"), ""); + + // list all available audio input devices + devs = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); + found_preferred_device = false; + for (int i=0;iaddItem(devs.at(i).deviceName(), devs.at(i).deviceName()); + if (!found_preferred_device + && devs.at(i).deviceName() == olive::CurrentConfig.preferred_audio_input) { + audio_input_devices->setCurrentIndex(audio_input_devices->count()-1); + found_preferred_device = true; + } + } + + audio_tab_layout->addWidget(audio_input_devices, 1, 1); + + audio_tab_layout->addWidget(new QLabel(tr("Sample Rate:")), 2, 0); + + audio_sample_rate = new QComboBox(); + combobox_audio_sample_rates(audio_sample_rate); + for (int i=0;icount();i++) { + if (audio_sample_rate->itemData(i).toInt() == olive::CurrentConfig.audio_rate) { + audio_sample_rate->setCurrentIndex(i); + break; + } + } + + audio_tab_layout->addWidget(audio_sample_rate, 2, 1); + + tabWidget->addTab(audio_tab, tr("Audio")); + + // Shortcuts + QWidget* shortcut_tab = new QWidget(this); + + QVBoxLayout* shortcut_layout = new QVBoxLayout(shortcut_tab); + + QLineEdit* key_search_line = new QLineEdit(shortcut_tab); + key_search_line->setPlaceholderText(tr("Search for action or shortcut")); + connect(key_search_line, SIGNAL(textChanged(const QString &)), this, SLOT(refine_shortcut_list(const QString &))); + + shortcut_layout->addWidget(key_search_line); + + keyboard_tree = new QTreeWidget(shortcut_tab); + QTreeWidgetItem* tree_header = keyboard_tree->headerItem(); + tree_header->setText(0, tr("Action")); + tree_header->setText(1, tr("Shortcut")); + shortcut_layout->addWidget(keyboard_tree); + + QHBoxLayout* reset_shortcut_layout = new QHBoxLayout(shortcut_tab); + + QPushButton* import_shortcut_button = new QPushButton(tr("Import"), shortcut_tab); + reset_shortcut_layout->addWidget(import_shortcut_button); + connect(import_shortcut_button, SIGNAL(clicked(bool)), this, SLOT(load_shortcut_file())); - QPushButton* export_shortcut_button = new QPushButton(tr("Export"), shortcut_tab); - reset_shortcut_layout->addWidget(export_shortcut_button); - connect(export_shortcut_button, SIGNAL(clicked(bool)), this, SLOT(save_shortcut_file())); + QPushButton* export_shortcut_button = new QPushButton(tr("Export"), shortcut_tab); + reset_shortcut_layout->addWidget(export_shortcut_button); + connect(export_shortcut_button, SIGNAL(clicked(bool)), this, SLOT(save_shortcut_file())); - reset_shortcut_layout->addStretch(); + reset_shortcut_layout->addStretch(); - QPushButton* reset_selected_shortcut_button = new QPushButton(tr("Reset Selected"), shortcut_tab); - reset_shortcut_layout->addWidget(reset_selected_shortcut_button); - connect(reset_selected_shortcut_button, SIGNAL(clicked(bool)), this, SLOT(reset_default_shortcut())); + QPushButton* reset_selected_shortcut_button = new QPushButton(tr("Reset Selected"), shortcut_tab); + reset_shortcut_layout->addWidget(reset_selected_shortcut_button); + connect(reset_selected_shortcut_button, SIGNAL(clicked(bool)), this, SLOT(reset_default_shortcut())); - QPushButton* reset_all_shortcut_button = new QPushButton(tr("Reset All"), shortcut_tab); - reset_shortcut_layout->addWidget(reset_all_shortcut_button); - connect(reset_all_shortcut_button, SIGNAL(clicked(bool)), this, SLOT(reset_all_shortcuts())); + QPushButton* reset_all_shortcut_button = new QPushButton(tr("Reset All"), shortcut_tab); + reset_shortcut_layout->addWidget(reset_all_shortcut_button); + connect(reset_all_shortcut_button, SIGNAL(clicked(bool)), this, SLOT(reset_all_shortcuts())); - shortcut_layout->addLayout(reset_shortcut_layout); + shortcut_layout->addLayout(reset_shortcut_layout); - tabWidget->addTab(shortcut_tab, tr("Keyboard")); + tabWidget->addTab(shortcut_tab, tr("Keyboard")); - verticalLayout->addWidget(tabWidget); + verticalLayout->addWidget(tabWidget); - QDialogButtonBox* buttonBox = new QDialogButtonBox(this); - buttonBox->setOrientation(Qt::Horizontal); - buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + QDialogButtonBox* buttonBox = new QDialogButtonBox(this); + buttonBox->setOrientation(Qt::Horizontal); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); - verticalLayout->addWidget(buttonBox); + verticalLayout->addWidget(buttonBox); - connect(buttonBox, SIGNAL(accepted()), this, SLOT(save())); - connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + connect(buttonBox, SIGNAL(accepted()), this, SLOT(save())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); } diff --git a/dialogs/preferencesdialog.h b/dialogs/preferencesdialog.h index 8aa3d232a..03d7bd4e5 100644 --- a/dialogs/preferencesdialog.h +++ b/dialogs/preferencesdialog.h @@ -35,68 +35,68 @@ #include class KeySequenceEditor : public QKeySequenceEdit { - Q_OBJECT + Q_OBJECT public: - KeySequenceEditor(QWidget *parent, QAction* a); - void set_action_shortcut(); - void reset_to_default(); - QString action_name(); - QString export_shortcut(); + KeySequenceEditor(QWidget *parent, QAction* a); + void set_action_shortcut(); + void reset_to_default(); + QString action_name(); + QString export_shortcut(); private: - QAction* action; + QAction* action; }; class PreferencesDialog : public QDialog { - Q_OBJECT + Q_OBJECT public: - explicit PreferencesDialog(QWidget *parent = nullptr); - ~PreferencesDialog(); + explicit PreferencesDialog(QWidget *parent = nullptr); + ~PreferencesDialog(); - void setup_kbd_shortcuts(QMenuBar* menu); + void setup_kbd_shortcuts(QMenuBar* menu); private slots: - void save(); - void reset_default_shortcut(); - void reset_all_shortcuts(); - bool refine_shortcut_list(const QString &, QTreeWidgetItem* parent = nullptr); - void load_shortcut_file(); - void save_shortcut_file(); - void browse_css_file(); - void delete_all_previews(); + void save(); + void reset_default_shortcut(); + void reset_all_shortcuts(); + bool refine_shortcut_list(const QString &, QTreeWidgetItem* parent = nullptr); + void load_shortcut_file(); + void save_shortcut_file(); + void browse_css_file(); + void delete_all_previews(); private: - void setup_ui(); - void setup_kbd_shortcut_worker(QMenu* menu, QTreeWidgetItem* parent); + void setup_ui(); + void setup_kbd_shortcut_worker(QMenu* menu, QTreeWidgetItem* parent); - // used to delete previews - // type can be: 't' for thumbnails, 'w' for waveforms, or 1 for all - void delete_previews(char type); + // used to delete previews + // type can be: 't' for thumbnails, 'w' for waveforms, or 1 for all + void delete_previews(char type); - QLineEdit* custom_css_fn; - QLineEdit* imgSeqFormatEdit; - QComboBox* recordingComboBox; - QRadioButton* accurateSeekButton; - QRadioButton* fastSeekButton; - QTreeWidget* keyboard_tree; - QDoubleSpinBox* upcoming_queue_spinbox; - QComboBox* upcoming_queue_type; - QDoubleSpinBox* previous_queue_spinbox; - QComboBox* previous_queue_type; - QSpinBox* effect_textbox_lines_field; - QCheckBox* use_software_fallbacks_checkbox; - QComboBox* audio_output_devices; - QComboBox* audio_input_devices; - QComboBox* audio_sample_rate; - QComboBox* language_combobox; - QSpinBox* thumbnail_res_spinbox; - QSpinBox* waveform_res_spinbox; - QCheckBox* add_default_effects_to_clips; + QLineEdit* custom_css_fn; + QLineEdit* imgSeqFormatEdit; + QComboBox* recordingComboBox; + QRadioButton* accurateSeekButton; + QRadioButton* fastSeekButton; + QTreeWidget* keyboard_tree; + QDoubleSpinBox* upcoming_queue_spinbox; + QComboBox* upcoming_queue_type; + QDoubleSpinBox* previous_queue_spinbox; + QComboBox* previous_queue_type; + QSpinBox* effect_textbox_lines_field; + QCheckBox* use_software_fallbacks_checkbox; + QComboBox* audio_output_devices; + QComboBox* audio_input_devices; + QComboBox* audio_sample_rate; + QComboBox* language_combobox; + QSpinBox* thumbnail_res_spinbox; + QSpinBox* waveform_res_spinbox; + QCheckBox* add_default_effects_to_clips; - QVector key_shortcut_actions; - QVector key_shortcut_items; - QVector key_shortcut_fields; + QVector key_shortcut_actions; + QVector key_shortcut_items; + QVector key_shortcut_fields; }; #endif // PREFERENCESDIALOG_H diff --git a/mainwindow.cpp b/mainwindow.cpp index 6eedb0426..169b9d087 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -71,893 +71,877 @@ MainWindow* olive::MainWindow; #define DEFAULT_CSS "QPushButton::checked { background: rgb(25, 25, 25); }" void MainWindow::setup_layout(bool reset) { - panel_project->show(); - panel_effect_controls->show(); - panel_footage_viewer->show(); - panel_sequence_viewer->show(); - panel_timeline->show(); - panel_graph_editor->hide(); + panel_project->show(); + panel_effect_controls->show(); + panel_footage_viewer->show(); + panel_sequence_viewer->show(); + panel_timeline->show(); + panel_graph_editor->hide(); - addDockWidget(Qt::TopDockWidgetArea, panel_project); - addDockWidget(Qt::TopDockWidgetArea, panel_graph_editor); - addDockWidget(Qt::TopDockWidgetArea, panel_footage_viewer); - tabifyDockWidget(panel_footage_viewer, panel_effect_controls); - panel_footage_viewer->raise(); - addDockWidget(Qt::TopDockWidgetArea, panel_sequence_viewer); - addDockWidget(Qt::BottomDockWidgetArea, panel_timeline); + addDockWidget(Qt::TopDockWidgetArea, panel_project); + addDockWidget(Qt::TopDockWidgetArea, panel_graph_editor); + addDockWidget(Qt::TopDockWidgetArea, panel_footage_viewer); + tabifyDockWidget(panel_footage_viewer, panel_effect_controls); + panel_footage_viewer->raise(); + addDockWidget(Qt::TopDockWidgetArea, panel_sequence_viewer); + addDockWidget(Qt::BottomDockWidgetArea, panel_timeline); - // load panels from file - if (!reset) { - QFile panel_config(get_config_path() + "/layout"); - if (panel_config.exists() && panel_config.open(QFile::ReadOnly)) { - restoreState(panel_config.readAll(), 0); - panel_config.close(); - } - } + // load panels from file + if (!reset) { + QFile panel_config(get_config_path() + "/layout"); + if (panel_config.exists() && panel_config.open(QFile::ReadOnly)) { + restoreState(panel_config.readAll(), 0); + panel_config.close(); + } + } - layout()->update(); + layout()->update(); } MainWindow::MainWindow(QWidget *parent) : - QMainWindow(parent), - first_show(true) + QMainWindow(parent), + first_show(true) { - qRegisterMetaType(); + qRegisterMetaType(); - init_custom_cursors(); + init_custom_cursors(); - open_debug_file(); + open_debug_file(); - olive::DebugDialog = new DebugDialog(this); + olive::DebugDialog = new DebugDialog(this); - olive::MainWindow = this; + olive::MainWindow = this; - // set up style? + // set up style? - qApp->setStyle(QStyleFactory::create("Fusion")); - setStyleSheet(DEFAULT_CSS); + qApp->setStyle(QStyleFactory::create("Fusion")); + setStyleSheet(DEFAULT_CSS); - QPalette darkPalette; - darkPalette.setColor(QPalette::Window, QColor(53,53,53)); - darkPalette.setColor(QPalette::WindowText, Qt::white); - darkPalette.setColor(QPalette::Base, QColor(25,25,25)); - darkPalette.setColor(QPalette::AlternateBase, QColor(53,53,53)); - darkPalette.setColor(QPalette::ToolTipBase, QColor(25,25,25)); - darkPalette.setColor(QPalette::ToolTipText, Qt::white); - darkPalette.setColor(QPalette::Text, Qt::white); - darkPalette.setColor(QPalette::Button, QColor(53,53,53)); - darkPalette.setColor(QPalette::ButtonText, Qt::white); darkPalette.setColor(QPalette::BrightText, Qt::red); - darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(128, 128, 128)); - darkPalette.setColor(QPalette::Link, QColor(42, 130, 218)); - darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218)); - darkPalette.setColor(QPalette::HighlightedText, Qt::black); + QPalette darkPalette; + darkPalette.setColor(QPalette::Window, QColor(53,53,53)); + darkPalette.setColor(QPalette::WindowText, Qt::white); + darkPalette.setColor(QPalette::Base, QColor(25,25,25)); + darkPalette.setColor(QPalette::AlternateBase, QColor(53,53,53)); + darkPalette.setColor(QPalette::ToolTipBase, QColor(25,25,25)); + darkPalette.setColor(QPalette::ToolTipText, Qt::white); + darkPalette.setColor(QPalette::Text, Qt::white); + darkPalette.setColor(QPalette::Button, QColor(53,53,53)); + darkPalette.setColor(QPalette::ButtonText, Qt::white); darkPalette.setColor(QPalette::BrightText, Qt::red); + darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(128, 128, 128)); + darkPalette.setColor(QPalette::Link, QColor(42, 130, 218)); + darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218)); + darkPalette.setColor(QPalette::HighlightedText, Qt::black); - qApp->setPalette(darkPalette); + qApp->setPalette(darkPalette); - // end style - QWidget* centralWidget = new QWidget(this); - centralWidget->setMaximumSize(QSize(0, 0)); - setCentralWidget(centralWidget); + // end style + QWidget* centralWidget = new QWidget(this); + centralWidget->setMaximumSize(QSize(0, 0)); + setCentralWidget(centralWidget); - setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North); + setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North); - setDockNestingEnabled(true); + setDockNestingEnabled(true); - layout()->invalidate(); + layout()->invalidate(); - QString data_dir = get_data_path(); - if (!data_dir.isEmpty()) { - QDir dir(data_dir); - dir.mkpath("."); - if (dir.exists()) { - qint64 a_month_ago = QDateTime::currentMSecsSinceEpoch() - 2592000000; - qint64 a_week_ago = QDateTime::currentMSecsSinceEpoch() - 604800000; + QString data_dir = get_data_path(); + if (!data_dir.isEmpty()) { + QDir dir(data_dir); + dir.mkpath("."); + if (dir.exists()) { + qint64 a_month_ago = QDateTime::currentMSecsSinceEpoch() - 2592000000; + qint64 a_week_ago = QDateTime::currentMSecsSinceEpoch() - 604800000; - // TODO put delete functions in another thread? + // TODO put delete functions in another thread? - // delete auto-recoveries older than 7 days - QStringList old_autorecoveries = dir.entryList(QStringList("autorecovery.ove.*"), QDir::Files); - int deleted_ars = 0; - for (int i=0;i 0) qInfo() << "Deleted" << deleted_ars << "autorecovery" << ((deleted_ars == 1) ? "file that was" : "files that were") << "older than 7 days"; - - // delete previews older than 30 days - QDir preview_dir = QDir(dir.filePath("previews")); - if (preview_dir.exists()) { - deleted_ars = 0; - QStringList old_prevs = preview_dir.entryList(QDir::Files); - for (int i=0;i 0) qInfo() << "Deleted" << deleted_ars << "preview" << ((deleted_ars == 1) ? "file that was" : "files that were") << "last read over 30 days ago"; - } - - // search for open recents list - QFile f(olive::Global->get_recent_project_list_file()); - if (f.exists() && f.open(QFile::ReadOnly | QFile::Text)) { - QTextStream text_stream(&f); - while (true) { - QString line = text_stream.readLine(); - if (line.isNull()) { - break; - } else { - recent_projects.append(line); - } - } - f.close(); - } - } - } - QString config_path = get_config_path(); - if (!config_path.isEmpty()) { - QDir config_dir(config_path); - config_dir.mkpath("."); - QString config_fn = config_dir.filePath("config.xml"); - if (QFileInfo::exists(config_fn)) { - olive::CurrentConfig.load(config_fn); - - if (!olive::CurrentConfig.css_path.isEmpty()) { - load_css_from_file(olive::CurrentConfig.css_path); - } - } - } - - // load preferred language from file - QString language_file = olive::CurrentRuntimeConfig.external_translation_file.isEmpty() ? - olive::CurrentConfig.language_file : - olive::CurrentRuntimeConfig.external_translation_file; - - if (!language_file.isEmpty()) { - - // translation files are stored relative to app path (see GitHub issue #454) - QString full_language_path = QDir(get_app_path()).filePath(language_file); - - if (QFileInfo::exists(full_language_path)) { - QTranslator* translator = new QTranslator(this); - translator->load(full_language_path); - QApplication::installTranslator(translator); - } else { - qWarning() << "Failed to load translation file" << full_language_path << ". No language will be loaded."; + // delete auto-recoveries older than 7 days + QStringList old_autorecoveries = dir.entryList(QStringList("autorecovery.ove.*"), QDir::Files); + int deleted_ars = 0; + for (int i=0;i 0) qInfo() << "Deleted" << deleted_ars << "autorecovery" << ((deleted_ars == 1) ? "file that was" : "files that were") << "older than 7 days"; - alloc_panels(this); + // delete previews older than 30 days + QDir preview_dir = QDir(dir.filePath("previews")); + if (preview_dir.exists()) { + deleted_ars = 0; + QStringList old_prevs = preview_dir.entryList(QDir::Files); + for (int i=0;i 0) qInfo() << "Deleted" << deleted_ars << "preview" << ((deleted_ars == 1) ? "file that was" : "files that were") << "last read over 30 days ago"; + } - QStatusBar* statusBar = new QStatusBar(this); - statusBar->showMessage(tr("Welcome to %1").arg(olive::AppName)); - setStatusBar(statusBar); + // search for open recents list + QFile f(olive::Global->get_recent_project_list_file()); + if (f.exists() && f.open(QFile::ReadOnly | QFile::Text)) { + QTextStream text_stream(&f); + while (true) { + QString line = text_stream.readLine(); + if (line.isNull()) { + break; + } else { + recent_projects.append(line); + } + } + f.close(); + } + } + } + QString config_path = get_config_path(); + if (!config_path.isEmpty()) { + QDir config_dir(config_path); + config_dir.mkpath("."); + QString config_fn = config_dir.filePath("config.xml"); + if (QFileInfo::exists(config_fn)) { + olive::CurrentConfig.load(config_fn); - // populate menu bars - setup_menus(); + if (!olive::CurrentConfig.css_path.isEmpty()) { + load_css_from_file(olive::CurrentConfig.css_path); + } + } + } - olive::Global->check_for_autorecovery_file(); + // load preferred language from file + olive::Global->load_translation_from_config(); - // set up panel layout - setup_layout(false); + alloc_panels(this); - // set up output audio device - init_audio(); + QStatusBar* statusBar = new QStatusBar(this); + statusBar->showMessage(tr("Welcome to %1").arg(olive::AppName)); + setStatusBar(statusBar); - // start omnipotent proxy generator process - proxy_generator.start(); + // populate menu bars + setup_menus(); - // set default window title - updateTitle(); + olive::Global->check_for_autorecovery_file(); + + // set up panel layout + setup_layout(false); + + // set up output audio device + init_audio(); + + // start omnipotent proxy generator process + proxy_generator.start(); + + // set default window title + updateTitle(); } MainWindow::~MainWindow() { - free_panels(); - close_debug_file(); + free_panels(); + close_debug_file(); } void kbd_shortcut_processor(QByteArray& file, QMenu* menu, bool save, bool first) { - QList actions = menu->actions(); - for (int i=0;imenu() != nullptr) { - kbd_shortcut_processor(file, a->menu(), save, first); - } else if (!a->isSeparator()) { - if (save) { - // saving custom shortcuts - if (!a->property("default").isNull()) { - QKeySequence defks(a->property("default").toString()); - if (a->shortcut() != defks) { - // custom shortcut - if (!file.isEmpty()) file.append('\n'); - file.append(a->property("id").toString()); - file.append('\t'); - file.append(a->shortcut().toString()); - } - } - } else { - // loading custom shortcuts - if (first) { - // store default shortcut - a->setProperty("default", a->shortcut().toString()); - } else { - // restore default shortcut - a->setShortcut(a->property("default").toString()); - } - if (!a->property("id").isNull()) { - QString comp_str = a->property("id").toString(); - int shortcut_index = file.indexOf(comp_str); - if (shortcut_index == 0 || (shortcut_index > 0 && file.at(shortcut_index-1) == '\n')) { - shortcut_index += comp_str.size() + 1; - QString shortcut; - while (shortcut_index < file.size() && file.at(shortcut_index) != '\n') { - shortcut.append(file.at(shortcut_index)); - shortcut_index++; - } - QKeySequence ks(shortcut); - if (!ks.isEmpty()) { - a->setShortcut(ks); - } - } - } - a->setShortcutContext(Qt::ApplicationShortcut); - } - } - } + QList actions = menu->actions(); + for (int i=0;imenu() != nullptr) { + kbd_shortcut_processor(file, a->menu(), save, first); + } else if (!a->isSeparator()) { + if (save) { + // saving custom shortcuts + if (!a->property("default").isNull()) { + QKeySequence defks(a->property("default").toString()); + if (a->shortcut() != defks) { + // custom shortcut + if (!file.isEmpty()) file.append('\n'); + file.append(a->property("id").toString()); + file.append('\t'); + file.append(a->shortcut().toString()); + } + } + } else { + // loading custom shortcuts + if (first) { + // store default shortcut + a->setProperty("default", a->shortcut().toString()); + } else { + // restore default shortcut + a->setShortcut(a->property("default").toString()); + } + if (!a->property("id").isNull()) { + QString comp_str = a->property("id").toString(); + int shortcut_index = file.indexOf(comp_str); + if (shortcut_index == 0 || (shortcut_index > 0 && file.at(shortcut_index-1) == '\n')) { + shortcut_index += comp_str.size() + 1; + QString shortcut; + while (shortcut_index < file.size() && file.at(shortcut_index) != '\n') { + shortcut.append(file.at(shortcut_index)); + shortcut_index++; + } + QKeySequence ks(shortcut); + if (!ks.isEmpty()) { + a->setShortcut(ks); + } + } + } + a->setShortcutContext(Qt::ApplicationShortcut); + } + } + } } void MainWindow::load_shortcuts(const QString& fn) { - QByteArray shortcut_bytes; - QFile shortcut_path(fn); - if (shortcut_path.exists() && shortcut_path.open(QFile::ReadOnly)) { - shortcut_bytes = shortcut_path.readAll(); - shortcut_path.close(); - } - QList menus = menuBar()->actions(); - for (int i=0;imenu(); - kbd_shortcut_processor(shortcut_bytes, menu, false, true); - } + QByteArray shortcut_bytes; + QFile shortcut_path(fn); + if (shortcut_path.exists() && shortcut_path.open(QFile::ReadOnly)) { + shortcut_bytes = shortcut_path.readAll(); + shortcut_path.close(); + } + QList menus = menuBar()->actions(); + for (int i=0;imenu(); + kbd_shortcut_processor(shortcut_bytes, menu, false, true); + } } void MainWindow::save_shortcuts(const QString& fn) { - // save main menu actions - QList menus = menuBar()->actions(); - QByteArray shortcut_file; - for (int i=0;imenu(); - kbd_shortcut_processor(shortcut_file, menu, true, false); - } - QFile shortcut_file_io(fn); - if (shortcut_file_io.open(QFile::WriteOnly)) { - shortcut_file_io.write(shortcut_file); - shortcut_file_io.close(); - } else { - qCritical() << "Failed to save shortcut file"; - } + // save main menu actions + QList menus = menuBar()->actions(); + QByteArray shortcut_file; + for (int i=0;imenu(); + kbd_shortcut_processor(shortcut_file, menu, true, false); + } + QFile shortcut_file_io(fn); + if (shortcut_file_io.open(QFile::WriteOnly)) { + shortcut_file_io.write(shortcut_file); + shortcut_file_io.close(); + } else { + qCritical() << "Failed to save shortcut file"; + } } void MainWindow::load_css_from_file(const QString &fn) { - QFile css_file(fn); - if (css_file.exists() && css_file.open(QFile::ReadOnly)) { - setStyleSheet(css_file.readAll()); - css_file.close(); - } else { - // set default stylesheet - setStyleSheet(DEFAULT_CSS); - } + QFile css_file(fn); + if (css_file.exists() && css_file.open(QFile::ReadOnly)) { + setStyleSheet(css_file.readAll()); + css_file.close(); + } else { + // set default stylesheet + setStyleSheet(DEFAULT_CSS); + } } void MainWindow::editMenu_About_To_Be_Shown() { - undo_action->setEnabled(olive::UndoStack.canUndo()); - redo_action->setEnabled(olive::UndoStack.canRedo()); + undo_action->setEnabled(olive::UndoStack.canUndo()); + redo_action->setEnabled(olive::UndoStack.canRedo()); } void MainWindow::setup_menus() { - QMenuBar* menuBar = new QMenuBar(this); - setMenuBar(menuBar); + QMenuBar* menuBar = new QMenuBar(this); + setMenuBar(menuBar); - // INITIALIZE FILE MENU + // INITIALIZE FILE MENU - QMenu* file_menu = menuBar->addMenu(tr("&File")); - connect(file_menu, SIGNAL(aboutToShow()), this, SLOT(fileMenu_About_To_Be_Shown())); + QMenu* file_menu = menuBar->addMenu(tr("&File")); + connect(file_menu, SIGNAL(aboutToShow()), this, SLOT(fileMenu_About_To_Be_Shown())); - QMenu* new_menu = file_menu->addMenu(tr("&New")); - olive::MenuHelper.make_new_menu(new_menu); + QMenu* new_menu = file_menu->addMenu(tr("&New")); + olive::MenuHelper.make_new_menu(new_menu); - file_menu->addAction(tr("&Open Project"), olive::Global.get(), SLOT(open_project()), QKeySequence("Ctrl+O"))->setProperty("id", "openproj"); + file_menu->addAction(tr("&Open Project"), olive::Global.get(), SLOT(open_project()), QKeySequence("Ctrl+O"))->setProperty("id", "openproj"); - clear_open_recent_action = new QAction(tr("Clear Recent List"), menuBar); - clear_open_recent_action->setProperty("id", "clearopenrecent"); - connect(clear_open_recent_action, SIGNAL(triggered()), panel_project, SLOT(clear_recent_projects())); + clear_open_recent_action = new QAction(tr("Clear Recent List"), menuBar); + clear_open_recent_action->setProperty("id", "clearopenrecent"); + connect(clear_open_recent_action, SIGNAL(triggered()), panel_project, SLOT(clear_recent_projects())); - open_recent = file_menu->addMenu(tr("Open Recent")); + open_recent = file_menu->addMenu(tr("Open Recent")); - open_recent->addAction(clear_open_recent_action); + open_recent->addAction(clear_open_recent_action); - file_menu->addAction(tr("&Save Project"), olive::Global.get(), SLOT(save_project()), QKeySequence("Ctrl+S"))->setProperty("id", "saveproj"); - file_menu->addAction(tr("Save Project &As"), olive::Global.get(), SLOT(save_project_as()), QKeySequence("Ctrl+Shift+S"))->setProperty("id", "saveprojas"); + file_menu->addAction(tr("&Save Project"), olive::Global.get(), SLOT(save_project()), QKeySequence("Ctrl+S"))->setProperty("id", "saveproj"); + file_menu->addAction(tr("Save Project &As"), olive::Global.get(), SLOT(save_project_as()), QKeySequence("Ctrl+Shift+S"))->setProperty("id", "saveprojas"); - file_menu->addSeparator(); + file_menu->addSeparator(); - file_menu->addAction(tr("&Import..."), panel_project, SLOT(import_dialog()), QKeySequence("Ctrl+I"))->setProperty("id", "import"); + file_menu->addAction(tr("&Import..."), panel_project, SLOT(import_dialog()), QKeySequence("Ctrl+I"))->setProperty("id", "import"); - file_menu->addSeparator(); + file_menu->addSeparator(); - file_menu->addAction(tr("&Export..."), olive::Global.get(), SLOT(open_export_dialog()), QKeySequence("Ctrl+M"))->setProperty("id", "export"); + file_menu->addAction(tr("&Export..."), olive::Global.get(), SLOT(open_export_dialog()), QKeySequence("Ctrl+M"))->setProperty("id", "export"); - file_menu->addSeparator(); + file_menu->addSeparator(); - file_menu->addAction(tr("E&xit"), this, SLOT(close()))->setProperty("id", "exit"); + file_menu->addAction(tr("E&xit"), this, SLOT(close()))->setProperty("id", "exit"); - // INITIALIZE EDIT MENU + // INITIALIZE EDIT MENU - QMenu* edit_menu = menuBar->addMenu(tr("&Edit")); - connect(edit_menu, SIGNAL(aboutToShow()), this, SLOT(editMenu_About_To_Be_Shown())); + QMenu* edit_menu = menuBar->addMenu(tr("&Edit")); + connect(edit_menu, SIGNAL(aboutToShow()), this, SLOT(editMenu_About_To_Be_Shown())); - undo_action = edit_menu->addAction(tr("&Undo"), olive::Global.get(), SLOT(undo()), QKeySequence("Ctrl+Z")); - undo_action->setProperty("id", "undo"); - redo_action = edit_menu->addAction(tr("Redo"), olive::Global.get(), SLOT(redo()), QKeySequence("Ctrl+Shift+Z")); - redo_action->setProperty("id", "redo"); + undo_action = edit_menu->addAction(tr("&Undo"), olive::Global.get(), SLOT(undo()), QKeySequence("Ctrl+Z")); + undo_action->setProperty("id", "undo"); + redo_action = edit_menu->addAction(tr("Redo"), olive::Global.get(), SLOT(redo()), QKeySequence("Ctrl+Shift+Z")); + redo_action->setProperty("id", "redo"); - edit_menu->addSeparator(); + edit_menu->addSeparator(); - olive::MenuHelper.make_edit_functions_menu(edit_menu); + olive::MenuHelper.make_edit_functions_menu(edit_menu); - edit_menu->addSeparator(); + edit_menu->addSeparator(); - edit_menu->addAction(tr("Select &All"), &olive::FocusFilter, SLOT(select_all()), QKeySequence("Ctrl+A"))->setProperty("id", "selectall"); + edit_menu->addAction(tr("Select &All"), &olive::FocusFilter, SLOT(select_all()), QKeySequence("Ctrl+A"))->setProperty("id", "selectall"); - edit_menu->addAction(tr("Deselect All"), panel_timeline, SLOT(deselect()), QKeySequence("Ctrl+Shift+A"))->setProperty("id", "deselectall"); + edit_menu->addAction(tr("Deselect All"), panel_timeline, SLOT(deselect()), QKeySequence("Ctrl+Shift+A"))->setProperty("id", "deselectall"); - edit_menu->addSeparator(); + edit_menu->addSeparator(); - olive::MenuHelper.make_clip_functions_menu(edit_menu); + olive::MenuHelper.make_clip_functions_menu(edit_menu); - edit_menu->addSeparator(); + edit_menu->addSeparator(); - edit_menu->addAction(tr("Ripple to In Point"), panel_timeline, SLOT(ripple_to_in_point()), QKeySequence("Q"))->setProperty("id", "rippletoin"); - edit_menu->addAction(tr("Ripple to Out Point"), panel_timeline, SLOT(ripple_to_out_point()), QKeySequence("W"))->setProperty("id", "rippletoout"); - edit_menu->addAction(tr("Edit to In Point"), panel_timeline, SLOT(edit_to_in_point()), QKeySequence("Ctrl+Alt+Q"))->setProperty("id", "edittoin"); - edit_menu->addAction(tr("Edit to Out Point"), panel_timeline, SLOT(edit_to_out_point()), QKeySequence("Ctrl+Alt+W"))->setProperty("id", "edittoout"); + edit_menu->addAction(tr("Ripple to In Point"), panel_timeline, SLOT(ripple_to_in_point()), QKeySequence("Q"))->setProperty("id", "rippletoin"); + edit_menu->addAction(tr("Ripple to Out Point"), panel_timeline, SLOT(ripple_to_out_point()), QKeySequence("W"))->setProperty("id", "rippletoout"); + edit_menu->addAction(tr("Edit to In Point"), panel_timeline, SLOT(edit_to_in_point()), QKeySequence("Ctrl+Alt+Q"))->setProperty("id", "edittoin"); + edit_menu->addAction(tr("Edit to Out Point"), panel_timeline, SLOT(edit_to_out_point()), QKeySequence("Ctrl+Alt+W"))->setProperty("id", "edittoout"); - edit_menu->addSeparator(); + edit_menu->addSeparator(); - olive::MenuHelper.make_inout_menu(edit_menu); - edit_menu->addAction(tr("Delete In/Out Point"), panel_timeline, SLOT(delete_inout()), QKeySequence(";"))->setProperty("id", "deleteinout"); - edit_menu->addAction(tr("Ripple Delete In/Out Point"), panel_timeline, SLOT(ripple_delete_inout()), QKeySequence("'"))->setProperty("id", "rippledeleteinout"); + olive::MenuHelper.make_inout_menu(edit_menu); + edit_menu->addAction(tr("Delete In/Out Point"), panel_timeline, SLOT(delete_inout()), QKeySequence(";"))->setProperty("id", "deleteinout"); + edit_menu->addAction(tr("Ripple Delete In/Out Point"), panel_timeline, SLOT(ripple_delete_inout()), QKeySequence("'"))->setProperty("id", "rippledeleteinout"); - edit_menu->addSeparator(); + edit_menu->addSeparator(); - edit_menu->addAction(tr("Set/Edit Marker"), &olive::FocusFilter, SLOT(set_marker()), QKeySequence("M"))->setProperty("id", "marker"); + edit_menu->addAction(tr("Set/Edit Marker"), &olive::FocusFilter, SLOT(set_marker()), QKeySequence("M"))->setProperty("id", "marker"); - // INITIALIZE VIEW MENU + // INITIALIZE VIEW MENU - QMenu* view_menu = menuBar->addMenu(tr("&View")); - connect(view_menu, SIGNAL(aboutToShow()), this, SLOT(viewMenu_About_To_Be_Shown())); + QMenu* view_menu = menuBar->addMenu(tr("&View")); + connect(view_menu, SIGNAL(aboutToShow()), this, SLOT(viewMenu_About_To_Be_Shown())); - 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("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"); - show_all = view_menu->addAction(tr("Toggle Show All"), panel_timeline, SLOT(toggle_show_all()), QKeySequence("\\")); - show_all->setProperty("id", "showall"); - show_all->setCheckable(true); + show_all = view_menu->addAction(tr("Toggle Show All"), panel_timeline, SLOT(toggle_show_all()), QKeySequence("\\")); + show_all->setProperty("id", "showall"); + show_all->setCheckable(true); - view_menu->addSeparator(); + view_menu->addSeparator(); - track_lines = view_menu->addAction(tr("Track Lines"), &olive::MenuHelper, SLOT(toggle_bool_action())); - track_lines->setProperty("id", "tracklines"); - track_lines->setCheckable(true); - track_lines->setData(reinterpret_cast(&olive::CurrentConfig.show_track_lines)); + track_lines = view_menu->addAction(tr("Track Lines"), &olive::MenuHelper, SLOT(toggle_bool_action())); + track_lines->setProperty("id", "tracklines"); + track_lines->setCheckable(true); + track_lines->setData(reinterpret_cast(&olive::CurrentConfig.show_track_lines)); - rectified_waveforms = view_menu->addAction(tr("Rectified Waveforms"), &olive::MenuHelper, SLOT(toggle_bool_action())); - rectified_waveforms->setProperty("id", "rectifiedwaveforms"); - rectified_waveforms->setCheckable(true); - rectified_waveforms->setData(reinterpret_cast(&olive::CurrentConfig.rectified_waveforms)); + rectified_waveforms = view_menu->addAction(tr("Rectified Waveforms"), &olive::MenuHelper, SLOT(toggle_bool_action())); + rectified_waveforms->setProperty("id", "rectifiedwaveforms"); + rectified_waveforms->setCheckable(true); + rectified_waveforms->setData(reinterpret_cast(&olive::CurrentConfig.rectified_waveforms)); - view_menu->addSeparator(); + view_menu->addSeparator(); - frames_action = view_menu->addAction(tr("Frames"), &olive::MenuHelper, SLOT(set_timecode_view())); - frames_action->setProperty("id", "modeframes"); - frames_action->setData(TIMECODE_FRAMES); - frames_action->setCheckable(true); - drop_frame_action = view_menu->addAction(tr("Drop Frame"), &olive::MenuHelper, SLOT(set_timecode_view())); - drop_frame_action->setProperty("id", "modedropframe"); - drop_frame_action->setData(TIMECODE_DROP); - drop_frame_action->setCheckable(true); - nondrop_frame_action = view_menu->addAction(tr("Non-Drop Frame"), &olive::MenuHelper, SLOT(set_timecode_view())); - nondrop_frame_action->setProperty("id", "modenondropframe"); - nondrop_frame_action->setData(TIMECODE_NONDROP); - nondrop_frame_action->setCheckable(true); - milliseconds_action = view_menu->addAction(tr("Milliseconds"), &olive::MenuHelper, SLOT(set_timecode_view())); - milliseconds_action->setProperty("id", "milliseconds"); - milliseconds_action->setData(TIMECODE_MILLISECONDS); - milliseconds_action->setCheckable(true); + frames_action = view_menu->addAction(tr("Frames"), &olive::MenuHelper, SLOT(set_timecode_view())); + frames_action->setProperty("id", "modeframes"); + frames_action->setData(TIMECODE_FRAMES); + frames_action->setCheckable(true); + drop_frame_action = view_menu->addAction(tr("Drop Frame"), &olive::MenuHelper, SLOT(set_timecode_view())); + drop_frame_action->setProperty("id", "modedropframe"); + drop_frame_action->setData(TIMECODE_DROP); + drop_frame_action->setCheckable(true); + nondrop_frame_action = view_menu->addAction(tr("Non-Drop Frame"), &olive::MenuHelper, SLOT(set_timecode_view())); + nondrop_frame_action->setProperty("id", "modenondropframe"); + nondrop_frame_action->setData(TIMECODE_NONDROP); + nondrop_frame_action->setCheckable(true); + milliseconds_action = view_menu->addAction(tr("Milliseconds"), &olive::MenuHelper, SLOT(set_timecode_view())); + milliseconds_action->setProperty("id", "milliseconds"); + milliseconds_action->setData(TIMECODE_MILLISECONDS); + milliseconds_action->setCheckable(true); - view_menu->addSeparator(); + view_menu->addSeparator(); - QMenu* title_safe_area_menu = view_menu->addMenu(tr("Title/Action Safe Area")); + QMenu* title_safe_area_menu = view_menu->addMenu(tr("Title/Action Safe Area")); - title_safe_off = title_safe_area_menu->addAction(tr("Off")); - title_safe_off->setProperty("id", "titlesafeoff"); - title_safe_off->setCheckable(true); - title_safe_off->setData(qSNaN()); - connect(title_safe_off, SIGNAL(triggered(bool)), &olive::MenuHelper, SLOT(set_titlesafe_from_menu())); + title_safe_off = title_safe_area_menu->addAction(tr("Off")); + title_safe_off->setProperty("id", "titlesafeoff"); + title_safe_off->setCheckable(true); + title_safe_off->setData(qSNaN()); + connect(title_safe_off, SIGNAL(triggered(bool)), &olive::MenuHelper, SLOT(set_titlesafe_from_menu())); - title_safe_default = title_safe_area_menu->addAction(tr("Default")); - title_safe_default->setProperty("id", "titlesafedefault"); - title_safe_default->setCheckable(true); - title_safe_default->setData(0.0); - connect(title_safe_default, SIGNAL(triggered(bool)), &olive::MenuHelper, SLOT(set_titlesafe_from_menu())); + title_safe_default = title_safe_area_menu->addAction(tr("Default")); + title_safe_default->setProperty("id", "titlesafedefault"); + title_safe_default->setCheckable(true); + title_safe_default->setData(0.0); + connect(title_safe_default, SIGNAL(triggered(bool)), &olive::MenuHelper, SLOT(set_titlesafe_from_menu())); - title_safe_43 = title_safe_area_menu->addAction(tr("4:3")); - title_safe_43->setProperty("id", "titlesafe43"); - title_safe_43->setCheckable(true); - title_safe_43->setData(4.0/3.0); - connect(title_safe_43, SIGNAL(triggered(bool)), &olive::MenuHelper, SLOT(set_titlesafe_from_menu())); + title_safe_43 = title_safe_area_menu->addAction(tr("4:3")); + title_safe_43->setProperty("id", "titlesafe43"); + title_safe_43->setCheckable(true); + title_safe_43->setData(4.0/3.0); + connect(title_safe_43, SIGNAL(triggered(bool)), &olive::MenuHelper, SLOT(set_titlesafe_from_menu())); - title_safe_169 = title_safe_area_menu->addAction(tr("16:9")); - title_safe_169->setProperty("id", "titlesafe169"); - title_safe_169->setCheckable(true); - title_safe_169->setData(16.0/9.0); - connect(title_safe_169, SIGNAL(triggered(bool)), &olive::MenuHelper, SLOT(set_titlesafe_from_menu())); + title_safe_169 = title_safe_area_menu->addAction(tr("16:9")); + title_safe_169->setProperty("id", "titlesafe169"); + title_safe_169->setCheckable(true); + title_safe_169->setData(16.0/9.0); + connect(title_safe_169, SIGNAL(triggered(bool)), &olive::MenuHelper, SLOT(set_titlesafe_from_menu())); - title_safe_custom = title_safe_area_menu->addAction(tr("Custom")); - title_safe_custom->setProperty("id", "titlesafecustom"); - title_safe_custom->setCheckable(true); - title_safe_custom->setData(-1.0); - connect(title_safe_custom, SIGNAL(triggered(bool)), &olive::MenuHelper, SLOT(set_titlesafe_from_menu())); - - view_menu->addSeparator(); - - full_screen = view_menu->addAction(tr("Full Screen"), this, SLOT(toggle_full_screen()), QKeySequence("F11")); - full_screen->setProperty("id", "fullscreen"); - full_screen->setCheckable(true); - - view_menu->addAction(tr("Full Screen Viewer"), &olive::FocusFilter, SLOT(set_viewer_fullscreen()))->setProperty("id", "fullscreenviewer"); - - // INITIALIZE PLAYBACK MENU - - QMenu* playback_menu = menuBar->addMenu(tr("&Playback")); - connect(playback_menu, SIGNAL(aboutToShow()), this, SLOT(playbackMenu_About_To_Be_Shown())); - - playback_menu->addAction(tr("Go to Start"), &olive::FocusFilter, SLOT(go_to_start()), QKeySequence("Home"))->setProperty("id", "gotostart"); - playback_menu->addAction(tr("Previous Frame"), &olive::FocusFilter, SLOT(prev_frame()), QKeySequence("Left"))->setProperty("id", "prevframe"); - playback_menu->addAction(tr("Play/Pause"), &olive::FocusFilter, SLOT(playpause()), QKeySequence("Space"))->setProperty("id", "playpause"); - playback_menu->addAction(tr("Play In to Out"), &olive::FocusFilter, SLOT(play_in_to_out()), QKeySequence("Shift+Space"))->setProperty("id", "playintoout"); - playback_menu->addAction(tr("Next Frame"), &olive::FocusFilter, SLOT(next_frame()), QKeySequence("Right"))->setProperty("id", "nextframe"); - playback_menu->addAction(tr("Go to End"), &olive::FocusFilter, SLOT(go_to_end()), QKeySequence("End"))->setProperty("id", "gotoend"); - playback_menu->addSeparator(); - playback_menu->addAction(tr("Go to Previous Cut"), panel_timeline, SLOT(previous_cut()), QKeySequence("Up"))->setProperty("id", "prevcut"); - playback_menu->addAction(tr("Go to Next Cut"), panel_timeline, SLOT(next_cut()), QKeySequence("Down"))->setProperty("id", "nextcut"); - playback_menu->addSeparator(); - playback_menu->addAction(tr("Go to In Point"), &olive::FocusFilter, SLOT(go_to_in()), QKeySequence("Shift+I"))->setProperty("id", "gotoin"); - playback_menu->addAction(tr("Go to Out Point"), &olive::FocusFilter, SLOT(go_to_out()), QKeySequence("Shift+O"))->setProperty("id", "gotoout"); - playback_menu->addSeparator(); - playback_menu->addAction(tr("Shuttle Left"), &olive::FocusFilter, SLOT(decrease_speed()), QKeySequence("J"))->setProperty("id", "decspeed"); - playback_menu->addAction(tr("Shuttle Stop"), &olive::FocusFilter, SLOT(pause()), QKeySequence("K"))->setProperty("id", "pause"); - playback_menu->addAction(tr("Shuttle Right"), &olive::FocusFilter, SLOT(increase_speed()), QKeySequence("L"))->setProperty("id", "incspeed"); - playback_menu->addSeparator(); - - loop_action = playback_menu->addAction(tr("Loop"), &olive::MenuHelper, SLOT(toggle_bool_action())); - loop_action->setProperty("id", "loop"); - loop_action->setCheckable(true); - loop_action->setData(reinterpret_cast(&olive::CurrentConfig.loop)); - - // INITIALIZE WINDOW MENU - - window_menu = menuBar->addMenu(tr("&Window")); - connect(window_menu, SIGNAL(aboutToShow()), this, SLOT(windowMenu_About_To_Be_Shown())); - - QAction* window_project_action = window_menu->addAction(tr("Project"), this, SLOT(toggle_panel_visibility())); - window_project_action->setProperty("id", "panelproject"); - window_project_action->setCheckable(true); - window_project_action->setData(reinterpret_cast(panel_project)); - - QAction* window_effectcontrols_action = window_menu->addAction(tr("Effect Controls"), this, SLOT(toggle_panel_visibility())); - window_effectcontrols_action->setProperty("id", "paneleffectcontrols"); - window_effectcontrols_action->setCheckable(true); - window_effectcontrols_action->setData(reinterpret_cast(panel_effect_controls)); - - QAction* window_timeline_action = window_menu->addAction(tr("Timeline"), this, SLOT(toggle_panel_visibility())); - window_timeline_action->setProperty("id", "paneltimeline"); - window_timeline_action->setCheckable(true); - window_timeline_action->setData(reinterpret_cast(panel_timeline)); - - QAction* window_graph_editor_action = window_menu->addAction(tr("Graph Editor"), this, SLOT(toggle_panel_visibility())); - window_graph_editor_action->setProperty("id", "panelgrapheditor"); - window_graph_editor_action->setCheckable(true); - window_graph_editor_action->setData(reinterpret_cast(panel_graph_editor)); - - QAction* window_footageviewer_action = window_menu->addAction(tr("Media Viewer"), this, SLOT(toggle_panel_visibility())); - window_footageviewer_action->setProperty("id", "panelfootageviewer"); - window_footageviewer_action->setCheckable(true); - window_footageviewer_action->setData(reinterpret_cast(panel_footage_viewer)); - - QAction* window_sequenceviewer_action = window_menu->addAction(tr("Sequence Viewer"), this, SLOT(toggle_panel_visibility())); - window_sequenceviewer_action->setProperty("id", "panelsequenceviewer"); - window_sequenceviewer_action->setCheckable(true); - window_sequenceviewer_action->setData(reinterpret_cast(panel_sequence_viewer)); - - window_menu->addSeparator(); - - window_menu->addAction(tr("Maximize Panel"), this, SLOT(maximize_panel()), QKeySequence("`"))->setProperty("id", "maximizepanel"); - - window_menu->addSeparator(); - - window_menu->addAction(tr("Reset to Default Layout"), this, SLOT(reset_layout()))->setProperty("id", "resetdefaultlayout"); - - // INITIALIZE TOOLS MENU - - QMenu* tools_menu = menuBar->addMenu(tr("&Tools")); - connect(tools_menu, SIGNAL(aboutToShow()), this, SLOT(toolMenu_About_To_Be_Shown())); - - pointer_tool_action = tools_menu->addAction(tr("Pointer Tool"), &olive::MenuHelper, SLOT(menu_click_button()), QKeySequence("V")); - pointer_tool_action->setProperty("id", "pointertool"); - pointer_tool_action->setCheckable(true); - pointer_tool_action->setData(reinterpret_cast(panel_timeline->toolArrowButton)); - - edit_tool_action = tools_menu->addAction(tr("Edit Tool"), &olive::MenuHelper, SLOT(menu_click_button()), QKeySequence("X")); - edit_tool_action->setProperty("id", "edittool"); - edit_tool_action->setCheckable(true); - edit_tool_action->setData(reinterpret_cast(panel_timeline->toolEditButton)); - - ripple_tool_action = tools_menu->addAction(tr("Ripple Tool"), &olive::MenuHelper, SLOT(menu_click_button()), QKeySequence("B")); - ripple_tool_action->setProperty("id", "rippletool"); - ripple_tool_action->setCheckable(true); - ripple_tool_action->setData(reinterpret_cast(panel_timeline->toolRippleButton)); - - razor_tool_action = tools_menu->addAction(tr("Razor Tool"), &olive::MenuHelper, SLOT(menu_click_button()), QKeySequence("C")); - razor_tool_action->setProperty("id", "razortool"); - razor_tool_action->setCheckable(true); - razor_tool_action->setData(reinterpret_cast(panel_timeline->toolRazorButton)); - - slip_tool_action = tools_menu->addAction(tr("Slip Tool"), &olive::MenuHelper, SLOT(menu_click_button()), QKeySequence("Y")); - slip_tool_action->setProperty("id", "sliptool"); - slip_tool_action->setCheckable(true); - slip_tool_action->setData(reinterpret_cast(panel_timeline->toolSlipButton)); - - slide_tool_action = tools_menu->addAction(tr("Slide Tool"), &olive::MenuHelper, SLOT(menu_click_button()), QKeySequence("U")); - slide_tool_action->setProperty("id", "slidetool"); - slide_tool_action->setCheckable(true); - slide_tool_action->setData(reinterpret_cast(panel_timeline->toolSlideButton)); - - hand_tool_action = tools_menu->addAction(tr("Hand Tool"), &olive::MenuHelper, SLOT(menu_click_button()), QKeySequence("H")); - hand_tool_action->setProperty("id", "handtool"); - hand_tool_action->setCheckable(true); - hand_tool_action->setData(reinterpret_cast(panel_timeline->toolHandButton)); - - transition_tool_action = tools_menu->addAction(tr("Transition Tool"), &olive::MenuHelper, SLOT(menu_click_button()), QKeySequence("T")); - transition_tool_action->setProperty("id", "transitiontool"); - transition_tool_action->setCheckable(true); - transition_tool_action->setData(reinterpret_cast(panel_timeline->toolTransitionButton)); - - tools_menu->addSeparator(); - - snap_toggle = tools_menu->addAction(tr("Enable Snapping"), &olive::MenuHelper, SLOT(menu_click_button()), QKeySequence("S")); - snap_toggle->setProperty("id", "snapping"); - snap_toggle->setCheckable(true); - snap_toggle->setData(reinterpret_cast(panel_timeline->snappingButton)); - - tools_menu->addSeparator(); - - selecting_also_seeks = tools_menu->addAction(tr("Selecting Also Seeks"), &olive::MenuHelper, SLOT(toggle_bool_action())); - selecting_also_seeks->setProperty("id", "selectingalsoseeks"); - selecting_also_seeks->setCheckable(true); - selecting_also_seeks->setData(reinterpret_cast(&olive::CurrentConfig.select_also_seeks)); - - edit_tool_also_seeks = tools_menu->addAction(tr("Edit Tool Also Seeks"), &olive::MenuHelper, SLOT(toggle_bool_action())); - edit_tool_also_seeks->setProperty("id", "editalsoseeks"); - edit_tool_also_seeks->setCheckable(true); - edit_tool_also_seeks->setData(reinterpret_cast(&olive::CurrentConfig.edit_tool_also_seeks)); - - edit_tool_selects_links = tools_menu->addAction(tr("Edit Tool Selects Links"), &olive::MenuHelper, SLOT(toggle_bool_action())); - edit_tool_selects_links->setProperty("id", "editselectslinks"); - edit_tool_selects_links->setCheckable(true); - edit_tool_selects_links->setData(reinterpret_cast(&olive::CurrentConfig.edit_tool_selects_links)); - - seek_also_selects = tools_menu->addAction(tr("Seek Also Selects"), &olive::MenuHelper, SLOT(toggle_bool_action())); - seek_also_selects->setProperty("id", "seekalsoselects"); - seek_also_selects->setCheckable(true); - seek_also_selects->setData(reinterpret_cast(&olive::CurrentConfig.seek_also_selects)); - - seek_to_end_of_pastes = tools_menu->addAction(tr("Seek to the End of Pastes"), &olive::MenuHelper, SLOT(toggle_bool_action())); - seek_to_end_of_pastes->setProperty("id", "seektoendofpastes"); - seek_to_end_of_pastes->setCheckable(true); - seek_to_end_of_pastes->setData(reinterpret_cast(&olive::CurrentConfig.paste_seeks)); - - scroll_wheel_zooms = tools_menu->addAction(tr("Scroll Wheel Zooms"), &olive::MenuHelper, SLOT(toggle_bool_action())); - scroll_wheel_zooms->setProperty("id", "scrollwheelzooms"); - scroll_wheel_zooms->setCheckable(true); - scroll_wheel_zooms->setData(reinterpret_cast(&olive::CurrentConfig.scroll_zooms)); - - enable_drag_files_to_timeline = tools_menu->addAction(tr("Enable Drag Files to Timeline"), &olive::MenuHelper, SLOT(toggle_bool_action())); - enable_drag_files_to_timeline->setProperty("id", "enabledragfilestotimeline"); - enable_drag_files_to_timeline->setCheckable(true); - enable_drag_files_to_timeline->setData(reinterpret_cast(&olive::CurrentConfig.enable_drag_files_to_timeline)); - - autoscale_by_default = tools_menu->addAction(tr("Auto-Scale By Default"), &olive::MenuHelper, SLOT(toggle_bool_action())); - autoscale_by_default->setProperty("id", "autoscalebydefault"); - autoscale_by_default->setCheckable(true); - autoscale_by_default->setData(reinterpret_cast(&olive::CurrentConfig.autoscale_by_default)); - - enable_seek_to_import = tools_menu->addAction(tr("Enable Seek to Import"), &olive::MenuHelper, SLOT(toggle_bool_action())); - enable_seek_to_import->setProperty("id", "enableseektoimport"); - enable_seek_to_import->setCheckable(true); - enable_seek_to_import->setData(reinterpret_cast(&olive::CurrentConfig.enable_seek_to_import)); - - enable_audio_scrubbing = tools_menu->addAction(tr("Audio Scrubbing"), &olive::MenuHelper, SLOT(toggle_bool_action())); - enable_audio_scrubbing->setProperty("id", "audioscrubbing"); - enable_audio_scrubbing->setCheckable(true); - enable_audio_scrubbing->setData(reinterpret_cast(&olive::CurrentConfig.enable_audio_scrubbing)); - - enable_drop_on_media_to_replace = tools_menu->addAction(tr("Enable Drop on Media to Replace"), &olive::MenuHelper, SLOT(toggle_bool_action())); - enable_drop_on_media_to_replace->setProperty("id", "enabledropmediareplace"); - enable_drop_on_media_to_replace->setCheckable(true); - enable_drop_on_media_to_replace->setData(reinterpret_cast(&olive::CurrentConfig.drop_on_media_to_replace)); - - enable_hover_focus = tools_menu->addAction(tr("Enable Hover Focus"), &olive::MenuHelper, SLOT(toggle_bool_action())); - enable_hover_focus->setProperty("id", "hoverfocus"); - enable_hover_focus->setCheckable(true); - enable_hover_focus->setData(reinterpret_cast(&olive::CurrentConfig.hover_focus)); - - set_name_and_marker = tools_menu->addAction(tr("Ask For Name When Setting Marker"), &olive::MenuHelper, SLOT(toggle_bool_action())); - set_name_and_marker->setProperty("id", "asknamemarkerset"); - set_name_and_marker->setCheckable(true); - set_name_and_marker->setData(reinterpret_cast(&olive::CurrentConfig.set_name_with_marker)); - - tools_menu->addSeparator(); - - no_autoscroll = tools_menu->addAction(tr("No Auto-Scroll"), &olive::MenuHelper, SLOT(set_autoscroll())); - no_autoscroll->setProperty("id", "autoscrollno"); - no_autoscroll->setData(AUTOSCROLL_NO_SCROLL); - no_autoscroll->setCheckable(true); - - page_autoscroll = tools_menu->addAction(tr("Page Auto-Scroll"), &olive::MenuHelper, SLOT(set_autoscroll())); - page_autoscroll->setProperty("id", "autoscrollpage"); - page_autoscroll->setData(AUTOSCROLL_PAGE_SCROLL); - page_autoscroll->setCheckable(true); - - smooth_autoscroll = tools_menu->addAction(tr("Smooth Auto-Scroll"), &olive::MenuHelper, SLOT(set_autoscroll())); - smooth_autoscroll->setProperty("id", "autoscrollsmooth"); - smooth_autoscroll->setData(AUTOSCROLL_SMOOTH_SCROLL); - smooth_autoscroll->setCheckable(true); - - tools_menu->addSeparator(); - - tools_menu->addAction(tr("Preferences"), olive::Global.get(), SLOT(open_preferences()), QKeySequence("Ctrl+,"))->setProperty("id", "prefs"); + title_safe_custom = title_safe_area_menu->addAction(tr("Custom")); + title_safe_custom->setProperty("id", "titlesafecustom"); + title_safe_custom->setCheckable(true); + title_safe_custom->setData(-1.0); + connect(title_safe_custom, SIGNAL(triggered(bool)), &olive::MenuHelper, SLOT(set_titlesafe_from_menu())); + + view_menu->addSeparator(); + + full_screen = view_menu->addAction(tr("Full Screen"), this, SLOT(toggle_full_screen()), QKeySequence("F11")); + full_screen->setProperty("id", "fullscreen"); + full_screen->setCheckable(true); + + view_menu->addAction(tr("Full Screen Viewer"), &olive::FocusFilter, SLOT(set_viewer_fullscreen()))->setProperty("id", "fullscreenviewer"); + + // INITIALIZE PLAYBACK MENU + + QMenu* playback_menu = menuBar->addMenu(tr("&Playback")); + connect(playback_menu, SIGNAL(aboutToShow()), this, SLOT(playbackMenu_About_To_Be_Shown())); + + playback_menu->addAction(tr("Go to Start"), &olive::FocusFilter, SLOT(go_to_start()), QKeySequence("Home"))->setProperty("id", "gotostart"); + playback_menu->addAction(tr("Previous Frame"), &olive::FocusFilter, SLOT(prev_frame()), QKeySequence("Left"))->setProperty("id", "prevframe"); + playback_menu->addAction(tr("Play/Pause"), &olive::FocusFilter, SLOT(playpause()), QKeySequence("Space"))->setProperty("id", "playpause"); + playback_menu->addAction(tr("Play In to Out"), &olive::FocusFilter, SLOT(play_in_to_out()), QKeySequence("Shift+Space"))->setProperty("id", "playintoout"); + playback_menu->addAction(tr("Next Frame"), &olive::FocusFilter, SLOT(next_frame()), QKeySequence("Right"))->setProperty("id", "nextframe"); + playback_menu->addAction(tr("Go to End"), &olive::FocusFilter, SLOT(go_to_end()), QKeySequence("End"))->setProperty("id", "gotoend"); + playback_menu->addSeparator(); + playback_menu->addAction(tr("Go to Previous Cut"), panel_timeline, SLOT(previous_cut()), QKeySequence("Up"))->setProperty("id", "prevcut"); + playback_menu->addAction(tr("Go to Next Cut"), panel_timeline, SLOT(next_cut()), QKeySequence("Down"))->setProperty("id", "nextcut"); + playback_menu->addSeparator(); + playback_menu->addAction(tr("Go to In Point"), &olive::FocusFilter, SLOT(go_to_in()), QKeySequence("Shift+I"))->setProperty("id", "gotoin"); + playback_menu->addAction(tr("Go to Out Point"), &olive::FocusFilter, SLOT(go_to_out()), QKeySequence("Shift+O"))->setProperty("id", "gotoout"); + playback_menu->addSeparator(); + playback_menu->addAction(tr("Shuttle Left"), &olive::FocusFilter, SLOT(decrease_speed()), QKeySequence("J"))->setProperty("id", "decspeed"); + playback_menu->addAction(tr("Shuttle Stop"), &olive::FocusFilter, SLOT(pause()), QKeySequence("K"))->setProperty("id", "pause"); + playback_menu->addAction(tr("Shuttle Right"), &olive::FocusFilter, SLOT(increase_speed()), QKeySequence("L"))->setProperty("id", "incspeed"); + playback_menu->addSeparator(); + + loop_action = playback_menu->addAction(tr("Loop"), &olive::MenuHelper, SLOT(toggle_bool_action())); + loop_action->setProperty("id", "loop"); + loop_action->setCheckable(true); + loop_action->setData(reinterpret_cast(&olive::CurrentConfig.loop)); + + // INITIALIZE WINDOW MENU + + window_menu = menuBar->addMenu(tr("&Window")); + connect(window_menu, SIGNAL(aboutToShow()), this, SLOT(windowMenu_About_To_Be_Shown())); + + QAction* window_project_action = window_menu->addAction(tr("Project"), this, SLOT(toggle_panel_visibility())); + window_project_action->setProperty("id", "panelproject"); + window_project_action->setCheckable(true); + window_project_action->setData(reinterpret_cast(panel_project)); + + QAction* window_effectcontrols_action = window_menu->addAction(tr("Effect Controls"), this, SLOT(toggle_panel_visibility())); + window_effectcontrols_action->setProperty("id", "paneleffectcontrols"); + window_effectcontrols_action->setCheckable(true); + window_effectcontrols_action->setData(reinterpret_cast(panel_effect_controls)); + + QAction* window_timeline_action = window_menu->addAction(tr("Timeline"), this, SLOT(toggle_panel_visibility())); + window_timeline_action->setProperty("id", "paneltimeline"); + window_timeline_action->setCheckable(true); + window_timeline_action->setData(reinterpret_cast(panel_timeline)); + + QAction* window_graph_editor_action = window_menu->addAction(tr("Graph Editor"), this, SLOT(toggle_panel_visibility())); + window_graph_editor_action->setProperty("id", "panelgrapheditor"); + window_graph_editor_action->setCheckable(true); + window_graph_editor_action->setData(reinterpret_cast(panel_graph_editor)); + + QAction* window_footageviewer_action = window_menu->addAction(tr("Media Viewer"), this, SLOT(toggle_panel_visibility())); + window_footageviewer_action->setProperty("id", "panelfootageviewer"); + window_footageviewer_action->setCheckable(true); + window_footageviewer_action->setData(reinterpret_cast(panel_footage_viewer)); + + QAction* window_sequenceviewer_action = window_menu->addAction(tr("Sequence Viewer"), this, SLOT(toggle_panel_visibility())); + window_sequenceviewer_action->setProperty("id", "panelsequenceviewer"); + window_sequenceviewer_action->setCheckable(true); + window_sequenceviewer_action->setData(reinterpret_cast(panel_sequence_viewer)); + + window_menu->addSeparator(); + + window_menu->addAction(tr("Maximize Panel"), this, SLOT(maximize_panel()), QKeySequence("`"))->setProperty("id", "maximizepanel"); + + window_menu->addSeparator(); + + window_menu->addAction(tr("Reset to Default Layout"), this, SLOT(reset_layout()))->setProperty("id", "resetdefaultlayout"); + + // INITIALIZE TOOLS MENU + + QMenu* tools_menu = menuBar->addMenu(tr("&Tools")); + connect(tools_menu, SIGNAL(aboutToShow()), this, SLOT(toolMenu_About_To_Be_Shown())); + + pointer_tool_action = tools_menu->addAction(tr("Pointer Tool"), &olive::MenuHelper, SLOT(menu_click_button()), QKeySequence("V")); + pointer_tool_action->setProperty("id", "pointertool"); + pointer_tool_action->setCheckable(true); + pointer_tool_action->setData(reinterpret_cast(panel_timeline->toolArrowButton)); + + edit_tool_action = tools_menu->addAction(tr("Edit Tool"), &olive::MenuHelper, SLOT(menu_click_button()), QKeySequence("X")); + edit_tool_action->setProperty("id", "edittool"); + edit_tool_action->setCheckable(true); + edit_tool_action->setData(reinterpret_cast(panel_timeline->toolEditButton)); + + ripple_tool_action = tools_menu->addAction(tr("Ripple Tool"), &olive::MenuHelper, SLOT(menu_click_button()), QKeySequence("B")); + ripple_tool_action->setProperty("id", "rippletool"); + ripple_tool_action->setCheckable(true); + ripple_tool_action->setData(reinterpret_cast(panel_timeline->toolRippleButton)); + + razor_tool_action = tools_menu->addAction(tr("Razor Tool"), &olive::MenuHelper, SLOT(menu_click_button()), QKeySequence("C")); + razor_tool_action->setProperty("id", "razortool"); + razor_tool_action->setCheckable(true); + razor_tool_action->setData(reinterpret_cast(panel_timeline->toolRazorButton)); + + slip_tool_action = tools_menu->addAction(tr("Slip Tool"), &olive::MenuHelper, SLOT(menu_click_button()), QKeySequence("Y")); + slip_tool_action->setProperty("id", "sliptool"); + slip_tool_action->setCheckable(true); + slip_tool_action->setData(reinterpret_cast(panel_timeline->toolSlipButton)); + + slide_tool_action = tools_menu->addAction(tr("Slide Tool"), &olive::MenuHelper, SLOT(menu_click_button()), QKeySequence("U")); + slide_tool_action->setProperty("id", "slidetool"); + slide_tool_action->setCheckable(true); + slide_tool_action->setData(reinterpret_cast(panel_timeline->toolSlideButton)); + + hand_tool_action = tools_menu->addAction(tr("Hand Tool"), &olive::MenuHelper, SLOT(menu_click_button()), QKeySequence("H")); + hand_tool_action->setProperty("id", "handtool"); + hand_tool_action->setCheckable(true); + hand_tool_action->setData(reinterpret_cast(panel_timeline->toolHandButton)); + + transition_tool_action = tools_menu->addAction(tr("Transition Tool"), &olive::MenuHelper, SLOT(menu_click_button()), QKeySequence("T")); + transition_tool_action->setProperty("id", "transitiontool"); + transition_tool_action->setCheckable(true); + transition_tool_action->setData(reinterpret_cast(panel_timeline->toolTransitionButton)); + + tools_menu->addSeparator(); + + snap_toggle = tools_menu->addAction(tr("Enable Snapping"), &olive::MenuHelper, SLOT(menu_click_button()), QKeySequence("S")); + snap_toggle->setProperty("id", "snapping"); + snap_toggle->setCheckable(true); + snap_toggle->setData(reinterpret_cast(panel_timeline->snappingButton)); + + tools_menu->addSeparator(); + + selecting_also_seeks = tools_menu->addAction(tr("Selecting Also Seeks"), &olive::MenuHelper, SLOT(toggle_bool_action())); + selecting_also_seeks->setProperty("id", "selectingalsoseeks"); + selecting_also_seeks->setCheckable(true); + selecting_also_seeks->setData(reinterpret_cast(&olive::CurrentConfig.select_also_seeks)); + + edit_tool_also_seeks = tools_menu->addAction(tr("Edit Tool Also Seeks"), &olive::MenuHelper, SLOT(toggle_bool_action())); + edit_tool_also_seeks->setProperty("id", "editalsoseeks"); + edit_tool_also_seeks->setCheckable(true); + edit_tool_also_seeks->setData(reinterpret_cast(&olive::CurrentConfig.edit_tool_also_seeks)); + + edit_tool_selects_links = tools_menu->addAction(tr("Edit Tool Selects Links"), &olive::MenuHelper, SLOT(toggle_bool_action())); + edit_tool_selects_links->setProperty("id", "editselectslinks"); + edit_tool_selects_links->setCheckable(true); + edit_tool_selects_links->setData(reinterpret_cast(&olive::CurrentConfig.edit_tool_selects_links)); + + seek_also_selects = tools_menu->addAction(tr("Seek Also Selects"), &olive::MenuHelper, SLOT(toggle_bool_action())); + seek_also_selects->setProperty("id", "seekalsoselects"); + seek_also_selects->setCheckable(true); + seek_also_selects->setData(reinterpret_cast(&olive::CurrentConfig.seek_also_selects)); + + seek_to_end_of_pastes = tools_menu->addAction(tr("Seek to the End of Pastes"), &olive::MenuHelper, SLOT(toggle_bool_action())); + seek_to_end_of_pastes->setProperty("id", "seektoendofpastes"); + seek_to_end_of_pastes->setCheckable(true); + seek_to_end_of_pastes->setData(reinterpret_cast(&olive::CurrentConfig.paste_seeks)); + + scroll_wheel_zooms = tools_menu->addAction(tr("Scroll Wheel Zooms"), &olive::MenuHelper, SLOT(toggle_bool_action())); + scroll_wheel_zooms->setProperty("id", "scrollwheelzooms"); + scroll_wheel_zooms->setCheckable(true); + scroll_wheel_zooms->setData(reinterpret_cast(&olive::CurrentConfig.scroll_zooms)); + + enable_drag_files_to_timeline = tools_menu->addAction(tr("Enable Drag Files to Timeline"), &olive::MenuHelper, SLOT(toggle_bool_action())); + enable_drag_files_to_timeline->setProperty("id", "enabledragfilestotimeline"); + enable_drag_files_to_timeline->setCheckable(true); + enable_drag_files_to_timeline->setData(reinterpret_cast(&olive::CurrentConfig.enable_drag_files_to_timeline)); + + autoscale_by_default = tools_menu->addAction(tr("Auto-Scale By Default"), &olive::MenuHelper, SLOT(toggle_bool_action())); + autoscale_by_default->setProperty("id", "autoscalebydefault"); + autoscale_by_default->setCheckable(true); + autoscale_by_default->setData(reinterpret_cast(&olive::CurrentConfig.autoscale_by_default)); + + enable_seek_to_import = tools_menu->addAction(tr("Enable Seek to Import"), &olive::MenuHelper, SLOT(toggle_bool_action())); + enable_seek_to_import->setProperty("id", "enableseektoimport"); + enable_seek_to_import->setCheckable(true); + enable_seek_to_import->setData(reinterpret_cast(&olive::CurrentConfig.enable_seek_to_import)); + + enable_audio_scrubbing = tools_menu->addAction(tr("Audio Scrubbing"), &olive::MenuHelper, SLOT(toggle_bool_action())); + enable_audio_scrubbing->setProperty("id", "audioscrubbing"); + enable_audio_scrubbing->setCheckable(true); + enable_audio_scrubbing->setData(reinterpret_cast(&olive::CurrentConfig.enable_audio_scrubbing)); + + enable_drop_on_media_to_replace = tools_menu->addAction(tr("Enable Drop on Media to Replace"), &olive::MenuHelper, SLOT(toggle_bool_action())); + enable_drop_on_media_to_replace->setProperty("id", "enabledropmediareplace"); + enable_drop_on_media_to_replace->setCheckable(true); + enable_drop_on_media_to_replace->setData(reinterpret_cast(&olive::CurrentConfig.drop_on_media_to_replace)); + + enable_hover_focus = tools_menu->addAction(tr("Enable Hover Focus"), &olive::MenuHelper, SLOT(toggle_bool_action())); + enable_hover_focus->setProperty("id", "hoverfocus"); + enable_hover_focus->setCheckable(true); + enable_hover_focus->setData(reinterpret_cast(&olive::CurrentConfig.hover_focus)); + + set_name_and_marker = tools_menu->addAction(tr("Ask For Name When Setting Marker"), &olive::MenuHelper, SLOT(toggle_bool_action())); + set_name_and_marker->setProperty("id", "asknamemarkerset"); + set_name_and_marker->setCheckable(true); + set_name_and_marker->setData(reinterpret_cast(&olive::CurrentConfig.set_name_with_marker)); + + tools_menu->addSeparator(); + + no_autoscroll = tools_menu->addAction(tr("No Auto-Scroll"), &olive::MenuHelper, SLOT(set_autoscroll())); + no_autoscroll->setProperty("id", "autoscrollno"); + no_autoscroll->setData(AUTOSCROLL_NO_SCROLL); + no_autoscroll->setCheckable(true); + + page_autoscroll = tools_menu->addAction(tr("Page Auto-Scroll"), &olive::MenuHelper, SLOT(set_autoscroll())); + page_autoscroll->setProperty("id", "autoscrollpage"); + page_autoscroll->setData(AUTOSCROLL_PAGE_SCROLL); + page_autoscroll->setCheckable(true); + + smooth_autoscroll = tools_menu->addAction(tr("Smooth Auto-Scroll"), &olive::MenuHelper, SLOT(set_autoscroll())); + smooth_autoscroll->setProperty("id", "autoscrollsmooth"); + smooth_autoscroll->setData(AUTOSCROLL_SMOOTH_SCROLL); + smooth_autoscroll->setCheckable(true); + + tools_menu->addSeparator(); + + tools_menu->addAction(tr("Preferences"), olive::Global.get(), SLOT(open_preferences()), QKeySequence("Ctrl+,"))->setProperty("id", "prefs"); #ifdef QT_DEBUG - tools_menu->addAction(tr("Clear Undo"), olive::Global.get(), SLOT(clear_undo_stack()))->setProperty("id", "clearundo"); + tools_menu->addAction(tr("Clear Undo"), olive::Global.get(), SLOT(clear_undo_stack()))->setProperty("id", "clearundo"); #endif - // INITIALIZE HELP MENU + // INITIALIZE HELP MENU - QMenu* help_menu = menuBar->addMenu(tr("&Help")); + QMenu* help_menu = menuBar->addMenu(tr("&Help")); - help_menu->addAction(tr("A&ction Search"), olive::Global.get(), SLOT(open_action_search()), QKeySequence("/"))->setProperty("id", "actionsearch"); + help_menu->addAction(tr("A&ction Search"), olive::Global.get(), SLOT(open_action_search()), QKeySequence("/"))->setProperty("id", "actionsearch"); - help_menu->addSeparator(); + help_menu->addSeparator(); - help_menu->addAction(tr("Debug Log"), olive::Global.get(), SLOT(open_debug_log()))->setProperty("id", "debuglog"); + help_menu->addAction(tr("Debug Log"), olive::Global.get(), SLOT(open_debug_log()))->setProperty("id", "debuglog"); - help_menu->addSeparator(); + help_menu->addSeparator(); - help_menu->addAction(tr("&About..."), olive::Global.get(), SLOT(open_about_dialog()))->setProperty("id", "about"); + help_menu->addAction(tr("&About..."), olive::Global.get(), SLOT(open_about_dialog()))->setProperty("id", "about"); - load_shortcuts(get_config_path() + "/shortcuts"); + load_shortcuts(get_config_path() + "/shortcuts"); } void MainWindow::updateTitle() { - setWindowTitle(QString("%1 - %2[*]").arg(olive::AppName, - (olive::ActiveProjectFilename.isEmpty()) ? - tr("") : olive::ActiveProjectFilename) - ); + setWindowTitle(QString("%1 - %2[*]").arg(olive::AppName, + (olive::ActiveProjectFilename.isEmpty()) ? + tr("") : olive::ActiveProjectFilename) + ); } void MainWindow::closeEvent(QCloseEvent *e) { - if (olive::Global->can_close_project()) { - // stop proxy generator thread - proxy_generator.cancel(); + if (olive::Global->can_close_project()) { + // stop proxy generator thread + proxy_generator.cancel(); - panel_effect_controls->clear_effects(true); + panel_effect_controls->clear_effects(true); - set_sequence(nullptr); + set_sequence(nullptr); - panel_footage_viewer->viewer_widget->close_window(); - panel_sequence_viewer->viewer_widget->close_window(); + panel_footage_viewer->viewer_widget->close_window(); + panel_sequence_viewer->viewer_widget->close_window(); - panel_footage_viewer->set_main_sequence(); + panel_footage_viewer->set_main_sequence(); - QString data_dir = get_data_path(); - QString config_path = get_config_path(); - if (!data_dir.isEmpty() && !autorecovery_filename.isEmpty()) { - if (QFile::exists(autorecovery_filename)) { - QFile::rename(autorecovery_filename, autorecovery_filename + "." + QDateTime::currentDateTimeUtc().toString("yyyyMMddHHmmss")); - } - } - if (!config_path.isEmpty()) { - QDir config_dir = QDir(config_path); + QString data_dir = get_data_path(); + QString config_path = get_config_path(); + if (!data_dir.isEmpty() && !autorecovery_filename.isEmpty()) { + if (QFile::exists(autorecovery_filename)) { + QFile::rename(autorecovery_filename, autorecovery_filename + "." + QDateTime::currentDateTimeUtc().toString("yyyyMMddHHmmss")); + } + } + if (!config_path.isEmpty()) { + QDir config_dir = QDir(config_path); - QString config_fn = config_dir.filePath("config.xml"); + QString config_fn = config_dir.filePath("config.xml"); - // save settings - olive::CurrentConfig.save(config_fn); + // save settings + olive::CurrentConfig.save(config_fn); - // save panel layout - QFile panel_config(config_path + "/layout"); - if (panel_config.open(QFile::WriteOnly)) { - panel_config.write(saveState(0)); - panel_config.close(); - } else { - qCritical() << "Failed to save layout"; - } + // save panel layout + QFile panel_config(config_path + "/layout"); + if (panel_config.open(QFile::WriteOnly)) { + panel_config.write(saveState(0)); + panel_config.close(); + } else { + qCritical() << "Failed to save layout"; + } - save_shortcuts(config_path + "/shortcuts"); - } + save_shortcuts(config_path + "/shortcuts"); + } - stop_audio(); + stop_audio(); - e->accept(); - } else { - e->ignore(); - } + e->accept(); + } else { + e->ignore(); + } } void MainWindow::paintEvent(QPaintEvent *event) { - QMainWindow::paintEvent(event); + QMainWindow::paintEvent(event); - if (first_show) { - first_show = false; - emit finished_first_paint(); - } + if (first_show) { + first_show = false; + emit finished_first_paint(); + } } void MainWindow::reset_layout() { - setup_layout(true); + setup_layout(true); } void MainWindow::maximize_panel() { - // toggles between normal state and a state of one panel being maximized - if (temp_panel_state.isEmpty()) { - // get currently hovered panel - QDockWidget* focused_panel = get_focused_panel(true); + // toggles between normal state and a state of one panel being maximized + if (temp_panel_state.isEmpty()) { + // get currently hovered panel + QDockWidget* focused_panel = get_focused_panel(true); - // if the mouse is in fact hovering over a panel - if (focused_panel != nullptr) { - // store the current state of panels - temp_panel_state = saveState(); + // if the mouse is in fact hovering over a panel + if (focused_panel != nullptr) { + // store the current state of panels + temp_panel_state = saveState(); - // remove all dock widgets (kind of painful having to do each individually) - if (focused_panel != panel_project) removeDockWidget(panel_project); - if (focused_panel != panel_effect_controls) removeDockWidget(panel_effect_controls); - if (focused_panel != panel_timeline) removeDockWidget(panel_timeline); - if (focused_panel != panel_sequence_viewer) removeDockWidget(panel_sequence_viewer); - if (focused_panel != panel_footage_viewer) removeDockWidget(panel_footage_viewer); - if (focused_panel != panel_graph_editor) removeDockWidget(panel_graph_editor); - } - } else { - // we must be maximized, restore previous state - restoreState(temp_panel_state); + // remove all dock widgets (kind of painful having to do each individually) + if (focused_panel != panel_project) removeDockWidget(panel_project); + if (focused_panel != panel_effect_controls) removeDockWidget(panel_effect_controls); + if (focused_panel != panel_timeline) removeDockWidget(panel_timeline); + if (focused_panel != panel_sequence_viewer) removeDockWidget(panel_sequence_viewer); + if (focused_panel != panel_footage_viewer) removeDockWidget(panel_footage_viewer); + if (focused_panel != panel_graph_editor) removeDockWidget(panel_graph_editor); + } + } else { + // we must be maximized, restore previous state + restoreState(temp_panel_state); - // clear temp panel state for next maximize call - temp_panel_state.clear(); - } + // clear temp panel state for next maximize call + temp_panel_state.clear(); + } } void MainWindow::windowMenu_About_To_Be_Shown() { - QList window_actions = window_menu->actions(); - for (int i=0;idata().isNull()) { - a->setChecked(reinterpret_cast(a->data().value())->isVisible()); - } - } + QList window_actions = window_menu->actions(); + for (int i=0;idata().isNull()) { + a->setChecked(reinterpret_cast(a->data().value())->isVisible()); + } + } } void MainWindow::playbackMenu_About_To_Be_Shown() { - olive::MenuHelper.set_bool_action_checked(loop_action); + olive::MenuHelper.set_bool_action_checked(loop_action); } void MainWindow::viewMenu_About_To_Be_Shown() { - olive::MenuHelper.set_bool_action_checked(track_lines); + olive::MenuHelper.set_bool_action_checked(track_lines); - olive::MenuHelper.set_int_action_checked(frames_action, olive::CurrentConfig.timecode_view); - olive::MenuHelper.set_int_action_checked(drop_frame_action, olive::CurrentConfig.timecode_view); - olive::MenuHelper.set_int_action_checked(nondrop_frame_action, olive::CurrentConfig.timecode_view); - olive::MenuHelper.set_int_action_checked(milliseconds_action, olive::CurrentConfig.timecode_view); + olive::MenuHelper.set_int_action_checked(frames_action, olive::CurrentConfig.timecode_view); + olive::MenuHelper.set_int_action_checked(drop_frame_action, olive::CurrentConfig.timecode_view); + olive::MenuHelper.set_int_action_checked(nondrop_frame_action, olive::CurrentConfig.timecode_view); + olive::MenuHelper.set_int_action_checked(milliseconds_action, olive::CurrentConfig.timecode_view); - title_safe_off->setChecked(!olive::CurrentConfig.show_title_safe_area); - title_safe_default->setChecked(olive::CurrentConfig.show_title_safe_area - && !olive::CurrentConfig.use_custom_title_safe_ratio); - title_safe_43->setChecked(olive::CurrentConfig.show_title_safe_area - && olive::CurrentConfig.use_custom_title_safe_ratio - && qFuzzyCompare(olive::CurrentConfig.custom_title_safe_ratio, title_safe_43->data().toDouble())); - title_safe_169->setChecked(olive::CurrentConfig.show_title_safe_area - && olive::CurrentConfig.use_custom_title_safe_ratio - && qFuzzyCompare(olive::CurrentConfig.custom_title_safe_ratio, title_safe_169->data().toDouble())); - title_safe_custom->setChecked(olive::CurrentConfig.show_title_safe_area - && olive::CurrentConfig.use_custom_title_safe_ratio - && !title_safe_43->isChecked() - && !title_safe_169->isChecked()); + title_safe_off->setChecked(!olive::CurrentConfig.show_title_safe_area); + title_safe_default->setChecked(olive::CurrentConfig.show_title_safe_area + && !olive::CurrentConfig.use_custom_title_safe_ratio); + title_safe_43->setChecked(olive::CurrentConfig.show_title_safe_area + && olive::CurrentConfig.use_custom_title_safe_ratio + && qFuzzyCompare(olive::CurrentConfig.custom_title_safe_ratio, title_safe_43->data().toDouble())); + title_safe_169->setChecked(olive::CurrentConfig.show_title_safe_area + && olive::CurrentConfig.use_custom_title_safe_ratio + && qFuzzyCompare(olive::CurrentConfig.custom_title_safe_ratio, title_safe_169->data().toDouble())); + title_safe_custom->setChecked(olive::CurrentConfig.show_title_safe_area + && olive::CurrentConfig.use_custom_title_safe_ratio + && !title_safe_43->isChecked() + && !title_safe_169->isChecked()); - full_screen->setChecked(windowState() == Qt::WindowFullScreen); + full_screen->setChecked(windowState() == Qt::WindowFullScreen); - show_all->setChecked(panel_timeline->showing_all); + show_all->setChecked(panel_timeline->showing_all); } void MainWindow::toolMenu_About_To_Be_Shown() { - olive::MenuHelper.set_button_action_checked(pointer_tool_action); - olive::MenuHelper.set_button_action_checked(edit_tool_action); - olive::MenuHelper.set_button_action_checked(ripple_tool_action); - olive::MenuHelper.set_button_action_checked(razor_tool_action); - olive::MenuHelper.set_button_action_checked(slip_tool_action); - olive::MenuHelper.set_button_action_checked(slide_tool_action); - olive::MenuHelper.set_button_action_checked(hand_tool_action); - olive::MenuHelper.set_button_action_checked(transition_tool_action); - olive::MenuHelper.set_button_action_checked(snap_toggle); + olive::MenuHelper.set_button_action_checked(pointer_tool_action); + olive::MenuHelper.set_button_action_checked(edit_tool_action); + olive::MenuHelper.set_button_action_checked(ripple_tool_action); + olive::MenuHelper.set_button_action_checked(razor_tool_action); + olive::MenuHelper.set_button_action_checked(slip_tool_action); + olive::MenuHelper.set_button_action_checked(slide_tool_action); + olive::MenuHelper.set_button_action_checked(hand_tool_action); + olive::MenuHelper.set_button_action_checked(transition_tool_action); + olive::MenuHelper.set_button_action_checked(snap_toggle); - olive::MenuHelper.set_bool_action_checked(selecting_also_seeks); - olive::MenuHelper.set_bool_action_checked(edit_tool_also_seeks); - olive::MenuHelper.set_bool_action_checked(edit_tool_selects_links); - olive::MenuHelper.set_bool_action_checked(seek_to_end_of_pastes); - olive::MenuHelper.set_bool_action_checked(scroll_wheel_zooms); - olive::MenuHelper.set_bool_action_checked(rectified_waveforms); - olive::MenuHelper.set_bool_action_checked(enable_drag_files_to_timeline); - olive::MenuHelper.set_bool_action_checked(autoscale_by_default); - olive::MenuHelper.set_bool_action_checked(enable_seek_to_import); - olive::MenuHelper.set_bool_action_checked(enable_audio_scrubbing); - olive::MenuHelper.set_bool_action_checked(enable_drop_on_media_to_replace); - olive::MenuHelper.set_bool_action_checked(enable_hover_focus); - olive::MenuHelper.set_bool_action_checked(set_name_and_marker); - olive::MenuHelper.set_bool_action_checked(seek_also_selects); + olive::MenuHelper.set_bool_action_checked(selecting_also_seeks); + olive::MenuHelper.set_bool_action_checked(edit_tool_also_seeks); + olive::MenuHelper.set_bool_action_checked(edit_tool_selects_links); + olive::MenuHelper.set_bool_action_checked(seek_to_end_of_pastes); + olive::MenuHelper.set_bool_action_checked(scroll_wheel_zooms); + olive::MenuHelper.set_bool_action_checked(rectified_waveforms); + olive::MenuHelper.set_bool_action_checked(enable_drag_files_to_timeline); + olive::MenuHelper.set_bool_action_checked(autoscale_by_default); + olive::MenuHelper.set_bool_action_checked(enable_seek_to_import); + olive::MenuHelper.set_bool_action_checked(enable_audio_scrubbing); + olive::MenuHelper.set_bool_action_checked(enable_drop_on_media_to_replace); + olive::MenuHelper.set_bool_action_checked(enable_hover_focus); + olive::MenuHelper.set_bool_action_checked(set_name_and_marker); + olive::MenuHelper.set_bool_action_checked(seek_also_selects); - olive::MenuHelper.set_int_action_checked(no_autoscroll, olive::CurrentConfig.autoscroll); - olive::MenuHelper.set_int_action_checked(page_autoscroll, olive::CurrentConfig.autoscroll); - olive::MenuHelper.set_int_action_checked(smooth_autoscroll, olive::CurrentConfig.autoscroll); + olive::MenuHelper.set_int_action_checked(no_autoscroll, olive::CurrentConfig.autoscroll); + olive::MenuHelper.set_int_action_checked(page_autoscroll, olive::CurrentConfig.autoscroll); + olive::MenuHelper.set_int_action_checked(smooth_autoscroll, olive::CurrentConfig.autoscroll); } void MainWindow::toggle_panel_visibility() { - QAction* action = static_cast(sender()); - QDockWidget* w = reinterpret_cast(action->data().value()); - w->setVisible(!w->isVisible()); + QAction* action = static_cast(sender()); + QDockWidget* w = reinterpret_cast(action->data().value()); + w->setVisible(!w->isVisible()); - // layout has changed, we're no longer in maximized panel mode, - // so we clear this byte array - temp_panel_state.clear(); + // layout has changed, we're no longer in maximized panel mode, + // so we clear this byte array + temp_panel_state.clear(); } void MainWindow::fileMenu_About_To_Be_Shown() { - if (recent_projects.size() > 0) { - open_recent->clear(); - open_recent->setEnabled(true); - for (int i=0;iaddAction(recent_projects.at(i)); - action->setProperty("keyignore", true); - action->setData(i); - connect(action, SIGNAL(triggered()), &olive::MenuHelper, SLOT(open_recent_from_menu())); - } - open_recent->addSeparator(); + if (recent_projects.size() > 0) { + open_recent->clear(); + open_recent->setEnabled(true); + for (int i=0;iaddAction(recent_projects.at(i)); + action->setProperty("keyignore", true); + action->setData(i); + connect(action, SIGNAL(triggered()), &olive::MenuHelper, SLOT(open_recent_from_menu())); + } + open_recent->addSeparator(); - open_recent->addAction(clear_open_recent_action); - } else { - open_recent->setEnabled(false); - } + open_recent->addAction(clear_open_recent_action); + } else { + open_recent->setEnabled(false); + } } void MainWindow::toggle_full_screen() { - if (windowState() == Qt::WindowFullScreen) { - setWindowState(Qt::WindowNoState); // seems to be necessary for it to return to Maximized correctly on Linux - setWindowState(Qt::WindowMaximized); - } else { - setWindowState(Qt::WindowFullScreen); - } + if (windowState() == Qt::WindowFullScreen) { + setWindowState(Qt::WindowNoState); // seems to be necessary for it to return to Maximized correctly on Linux + setWindowState(Qt::WindowMaximized); + } else { + setWindowState(Qt::WindowFullScreen); + } } diff --git a/olive.pro b/olive.pro index bee391b17..6864830e1 100644 --- a/olive.pro +++ b/olive.pro @@ -150,7 +150,8 @@ SOURCES += \ oliveglobal.cpp \ ui/focusfilter.cpp \ project/comboaction.cpp \ - ui/mediaiconservice.cpp + ui/mediaiconservice.cpp \ + ui/panel.cpp HEADERS += \ mainwindow.h \ @@ -258,7 +259,8 @@ HEADERS += \ project/projectelements.h \ ui/focusfilter.h \ project/comboaction.h \ - ui/mediaiconservice.h + ui/mediaiconservice.h \ + ui/panel.h FORMS += diff --git a/oliveglobal.cpp b/oliveglobal.cpp index 26c686899..174df5b9f 100644 --- a/oliveglobal.cpp +++ b/oliveglobal.cpp @@ -25,6 +25,7 @@ #include "panels/panels.h" #include "io/path.h" +#include "io/config.h" #include "playback/audio.h" @@ -41,6 +42,7 @@ #include #include #include +#include #include std::unique_ptr olive::Global; @@ -60,6 +62,9 @@ OliveGlobal::OliveGlobal() { // set default value enable_load_project_on_init = false; + + // alloc QTranslator + translator = std::unique_ptr(new QTranslator()); } const QString &OliveGlobal::get_project_file_filter() { @@ -106,7 +111,30 @@ void OliveGlobal::load_project_on_launch(const QString& s) { } QString OliveGlobal::get_recent_project_list_file() { - return get_data_dir().filePath("recents"); + return get_data_dir().filePath("recents"); +} + +void OliveGlobal::load_translation_from_config() { + QString language_file = olive::CurrentRuntimeConfig.external_translation_file.isEmpty() ? + olive::CurrentConfig.language_file : + olive::CurrentRuntimeConfig.external_translation_file; + + if (!language_file.isEmpty()) { + + // translation files are stored relative to app path (see GitHub issue #454) + QString full_language_path = QDir(get_app_path()).filePath(language_file); + + // remove translation + QApplication::removeTranslator(translator.get()); + + // load translation file + if (QFileInfo::exists(full_language_path) + && translator->load(full_language_path)) { + QApplication::installTranslator(translator.get()); + } else { + qWarning() << "Failed to load translation file" << full_language_path << ". No language will be loaded."; + } + } } void OliveGlobal::new_project() { diff --git a/oliveglobal.h b/oliveglobal.h index 7b3ffc2b1..1e43852c7 100644 --- a/oliveglobal.h +++ b/oliveglobal.h @@ -25,6 +25,7 @@ #include #include +#include /** * @brief The Olive Global class @@ -108,6 +109,11 @@ public: */ QString get_recent_project_list_file(); + /** + * @brief (Re)load translation file from olive::config + */ + void load_translation_from_config(); + public slots: /** * @brief Undo user's last action @@ -290,6 +296,11 @@ private: */ bool enable_load_project_on_init; + /** + * @brief Internal translator object that interfaces with the currently loaded language file + */ + std::unique_ptr translator; + private slots: diff --git a/panels/effectcontrols.cpp b/panels/effectcontrols.cpp index 6619b9701..85485ecd6 100644 --- a/panels/effectcontrols.cpp +++ b/panels/effectcontrols.cpp @@ -52,15 +52,13 @@ #include "debug.h" EffectControls::EffectControls(QWidget *parent) : - QDockWidget(parent), + Panel(parent), multiple(false), zoom(1), - panel_name(tr("Effects: ")), mode(kTransitionNone) { - setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - setup_ui(); + Retranslate(); clear_effects(false); headers->viewer = panel_sequence_viewer; @@ -277,7 +275,7 @@ void EffectControls::clear_effects(bool clear_cache) { headers->setVisible(false); keyframeView->setEnabled(false); if (clear_cache) selected_clips.clear(); - setWindowTitle(panel_name + "(none)"); + UpdateTitle(); } void EffectControls::deselect_all_effects(QWidget* sender) { @@ -298,6 +296,14 @@ void EffectControls::open_effect(QVBoxLayout* layout, EffectPtr e) { connect(container, SIGNAL(deselect_others(QWidget*)), this, SLOT(deselect_all_effects(QWidget*))); } +void EffectControls::UpdateTitle() { + if (selected_clips.empty()) { + setWindowTitle(panel_name + tr("(none)")); + } else { + setWindowTitle(panel_name + olive::ActiveSequence->clips.at(selected_clips.at(0))->name); + } +} + void EffectControls::setup_ui() { QWidget* contents = new QWidget(this); @@ -344,27 +350,24 @@ void EffectControls::setup_ui() { veHeaderLayout->setSpacing(0); veHeaderLayout->setMargin(0); - QPushButton* btnAddVideoEffect = new QPushButton(); + btnAddVideoEffect = new QPushButton(); btnAddVideoEffect->setIcon(QIcon(":/icons/add-effect.png")); - btnAddVideoEffect->setToolTip(tr("Add Video Effect")); veHeaderLayout->addWidget(btnAddVideoEffect); connect(btnAddVideoEffect, SIGNAL(clicked(bool)), this, SLOT(video_effect_click())); veHeaderLayout->addStretch(); - QLabel* lblVideoEffects = new QLabel(); + lblVideoEffects = new QLabel(); QFont font; font.setPointSize(9); lblVideoEffects->setFont(font); lblVideoEffects->setAlignment(Qt::AlignCenter); - lblVideoEffects->setText(tr("VIDEO EFFECTS")); veHeaderLayout->addWidget(lblVideoEffects); veHeaderLayout->addStretch(); - QPushButton* btnAddVideoTransition = new QPushButton(); + btnAddVideoTransition = new QPushButton(); btnAddVideoTransition->setIcon(QIcon(":/icons/add-transition.png")); - btnAddVideoTransition->setToolTip(tr("Add Video Transition")); connect(btnAddVideoTransition, SIGNAL(clicked(bool)), this, SLOT(video_transition_click())); veHeaderLayout->addWidget(btnAddVideoTransition); @@ -391,25 +394,22 @@ void EffectControls::setup_ui() { aeHeaderLayout->setSpacing(0); aeHeaderLayout->setMargin(0); - QPushButton* btnAddAudioEffect = new QPushButton(); + btnAddAudioEffect = new QPushButton(); btnAddAudioEffect->setIcon(QIcon(":/icons/add-effect.png")); - btnAddAudioEffect->setToolTip(tr("Add Audio Effect")); connect(btnAddAudioEffect, SIGNAL(clicked(bool)), this, SLOT(audio_effect_click())); aeHeaderLayout->addWidget(btnAddAudioEffect); aeHeaderLayout->addStretch(); - QLabel* lblAudioEffects = new QLabel(); + lblAudioEffects = new QLabel(); lblAudioEffects->setFont(font); lblAudioEffects->setAlignment(Qt::AlignCenter); - lblAudioEffects->setText(tr("AUDIO EFFECTS")); aeHeaderLayout->addWidget(lblAudioEffects); aeHeaderLayout->addStretch(); - QPushButton* btnAddAudioTransition = new QPushButton(); + btnAddAudioTransition = new QPushButton(); btnAddAudioTransition->setIcon(QIcon(":/icons/add-transition.png")); - btnAddAudioTransition->setToolTip(tr("Add Audio Transition")); connect(btnAddAudioTransition, SIGNAL(clicked(bool)), this, SLOT(audio_transition_click())); aeHeaderLayout->addWidget(btnAddAudioTransition); @@ -426,7 +426,6 @@ void EffectControls::setup_ui() { lblMultipleClipsSelected = new QLabel(); lblMultipleClipsSelected->setAlignment(Qt::AlignCenter); - lblMultipleClipsSelected->setText(tr("(Multiple clips selected)")); effects_area_layout->addWidget(lblMultipleClipsSelected); effects_area_layout->addStretch(); @@ -481,6 +480,20 @@ void EffectControls::setup_ui() { setWidget(contents); } +void EffectControls::Retranslate() { + panel_name = tr("Effects: "); + + btnAddVideoEffect->setToolTip(tr("Add Video Effect")); + lblVideoEffects->setText(tr("VIDEO EFFECTS")); + btnAddVideoTransition->setToolTip(tr("Add Video Transition")); + btnAddAudioEffect->setToolTip(tr("Add Audio Effect")); + lblAudioEffects->setText(tr("AUDIO EFFECTS")); + btnAddAudioTransition->setToolTip(tr("Add Audio Transition")); + lblMultipleClipsSelected->setText(tr("(Multiple clips selected)")); + + UpdateTitle(); +} + void EffectControls::update_scrollbar() { verticalScrollBar->setMaximum(qMax(0, effects_area->height() - keyframeView->height() - headers->height())); verticalScrollBar->setPageStep(verticalScrollBar->height()); @@ -525,13 +538,14 @@ void EffectControls::load_effects() { } } if (selected_clips.size() > 0) { - setWindowTitle(panel_name + olive::ActiveSequence->clips.at(selected_clips.at(0))->name); keyframeView->setEnabled(true); headers->setVisible(true); QTimer::singleShot(50, this, SLOT(queue_post_update())); } } + + UpdateTitle(); } void EffectControls::delete_effects() { diff --git a/panels/effectcontrols.h b/panels/effectcontrols.h index aee0c8f73..a37ebbf59 100644 --- a/panels/effectcontrols.h +++ b/panels/effectcontrols.h @@ -21,7 +21,6 @@ #ifndef EFFECTCONTROLS_H #define EFFECTCONTROLS_H -#include #include #include #include @@ -36,88 +35,97 @@ #include "ui/keyframeview.h" #include "ui/resizablescrollbar.h" #include "ui/keyframeview.h" +#include "ui/panel.h" class EffectsArea : public QWidget { - Q_OBJECT + Q_OBJECT public: - EffectsArea(QWidget* parent = 0); - QScrollArea* parent_widget; - KeyframeView* keyframe_area; - TimelineHeader* header; + EffectsArea(QWidget* parent = 0); + QScrollArea* parent_widget; + KeyframeView* keyframe_area; + TimelineHeader* header; public slots: - void receive_wheel_event(QWheelEvent* e); + void receive_wheel_event(QWheelEvent* e); }; -class EffectControls : public QDockWidget +class EffectControls : public Panel { - Q_OBJECT + Q_OBJECT public: - explicit EffectControls(QWidget *parent = 0); - ~EffectControls(); - int get_mode(); - void set_clips(QVector& clips, int mode); - void clear_effects(bool clear_cache); - void delete_effects(); - bool is_focused(); - void reload_clips(); - void set_zoom(bool in); - bool keyframe_focus(); - void delete_selected_keyframes(); - bool multiple; - void scroll_to_frame(long frame); + explicit EffectControls(QWidget *parent = 0); + ~EffectControls(); + int get_mode(); + void set_clips(QVector& clips, int mode); + void clear_effects(bool clear_cache); + void delete_effects(); + bool is_focused(); + void reload_clips(); + void set_zoom(bool in); + bool keyframe_focus(); + void delete_selected_keyframes(); + bool multiple; + void scroll_to_frame(long frame); - QVector selected_clips; + QVector selected_clips; - double zoom; + double zoom; - ResizableScrollBar* horizontalScrollBar; - QScrollBar* verticalScrollBar; + ResizableScrollBar* horizontalScrollBar; + QScrollBar* verticalScrollBar; - QMutex effects_loaded; + QMutex effects_loaded; - void add_effect_paste_action(QMenu* menu); + void add_effect_paste_action(QMenu* menu); public slots: - void cut(); - void copy(bool del = false); - void update_keyframes(); + void cut(); + void copy(bool del = false); + void update_keyframes(); private slots: - void menu_select(QAction* q); + void menu_select(QAction* q); - void video_effect_click(); - void audio_effect_click(); - void video_transition_click(); - void audio_transition_click(); + void video_effect_click(); + void audio_effect_click(); + void video_transition_click(); + void audio_transition_click(); - void deselect_all_effects(QWidget*); + void deselect_all_effects(QWidget*); - void update_scrollbar(); - void queue_post_update(); + void update_scrollbar(); + void queue_post_update(); - void effects_area_context_menu(); + void effects_area_context_menu(); protected: - void resizeEvent(QResizeEvent *event); + virtual void resizeEvent(QResizeEvent *event) override; + virtual void Retranslate() override; private: - void show_effect_menu(int type, int subtype); - void load_effects(); - void load_keyframes(); - void open_effect(QVBoxLayout* hlayout, EffectPtr e); + void show_effect_menu(int type, int subtype); + void load_effects(); + void load_keyframes(); + void open_effect(QVBoxLayout* hlayout, EffectPtr e); + void UpdateTitle(); - void setup_ui(); + void setup_ui(); - int effect_menu_type; - int effect_menu_subtype; - QString panel_name; - int mode; + int effect_menu_type; + int effect_menu_subtype; + QString panel_name; + int mode; - TimelineHeader* headers; - EffectsArea* effects_area; - QScrollArea* scrollArea; - QLabel* lblMultipleClipsSelected; - KeyframeView* keyframeView; - QWidget* video_effect_area; - QWidget* audio_effect_area; - QWidget* vcontainer; - QWidget* acontainer; + QPushButton* btnAddVideoEffect; + QLabel* lblVideoEffects; + QPushButton* btnAddVideoTransition; + QPushButton* btnAddAudioEffect; + QPushButton* btnAddAudioTransition; + QLabel* lblMultipleClipsSelected; + QLabel* lblAudioEffects; + TimelineHeader* headers; + EffectsArea* effects_area; + QScrollArea* scrollArea; + KeyframeView* keyframeView; + QWidget* video_effect_area; + QWidget* audio_effect_area; + QWidget* vcontainer; + QWidget* acontainer; }; #endif // EFFECTCONTROLS_H diff --git a/panels/grapheditor.cpp b/panels/grapheditor.cpp index 7475b852c..bf8e0148d 100644 --- a/panels/grapheditor.cpp +++ b/panels/grapheditor.cpp @@ -37,218 +37,226 @@ #include "panels.h" #include "debug.h" -GraphEditor::GraphEditor(QWidget* parent) : QDockWidget(parent), row(nullptr) { - setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); +GraphEditor::GraphEditor(QWidget* parent) : Panel(parent), row(nullptr) { + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - setWindowTitle(tr("Graph Editor")); - resize(720, 480); + resize(720, 480); - QWidget* main_widget = new QWidget(this); - QVBoxLayout* layout = new QVBoxLayout(main_widget); - setWidget(main_widget); + QWidget* main_widget = new QWidget(this); + QVBoxLayout* layout = new QVBoxLayout(main_widget); + setWidget(main_widget); - QWidget* tool_widget = new QWidget(); - tool_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); - QHBoxLayout* tools = new QHBoxLayout(tool_widget); + QWidget* tool_widget = new QWidget(); + tool_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); + QHBoxLayout* tools = new QHBoxLayout(tool_widget); - QWidget* left_tool_widget = new QWidget(); - QHBoxLayout* left_tool_layout = new QHBoxLayout(left_tool_widget); - left_tool_layout->setSpacing(0); - left_tool_layout->setMargin(0); - tools->addWidget(left_tool_widget); - QWidget* center_tool_widget = new QWidget(); - QHBoxLayout* center_tool_layout = new QHBoxLayout(center_tool_widget); - center_tool_layout->setSpacing(0); - center_tool_layout->setMargin(0); - tools->addWidget(center_tool_widget); - QWidget* right_tool_widget = new QWidget(); - QHBoxLayout* right_tool_layout = new QHBoxLayout(right_tool_widget); - right_tool_layout->setSpacing(0); - right_tool_layout->setMargin(0); - tools->addWidget(right_tool_widget); + QWidget* left_tool_widget = new QWidget(); + QHBoxLayout* left_tool_layout = new QHBoxLayout(left_tool_widget); + left_tool_layout->setSpacing(0); + left_tool_layout->setMargin(0); + tools->addWidget(left_tool_widget); + QWidget* center_tool_widget = new QWidget(); + QHBoxLayout* center_tool_layout = new QHBoxLayout(center_tool_widget); + center_tool_layout->setSpacing(0); + center_tool_layout->setMargin(0); + tools->addWidget(center_tool_widget); + QWidget* right_tool_widget = new QWidget(); + QHBoxLayout* right_tool_layout = new QHBoxLayout(right_tool_widget); + right_tool_layout->setSpacing(0); + right_tool_layout->setMargin(0); + tools->addWidget(right_tool_widget); - keyframe_nav = new KeyframeNavigator(nullptr, false); - keyframe_nav->enable_keyframes(true); - keyframe_nav->enable_keyframe_toggle(false); - left_tool_layout->addWidget(keyframe_nav); - left_tool_layout->addStretch(); + keyframe_nav = new KeyframeNavigator(nullptr, false); + keyframe_nav->enable_keyframes(true); + keyframe_nav->enable_keyframe_toggle(false); + left_tool_layout->addWidget(keyframe_nav); + left_tool_layout->addStretch(); - linear_button = new QPushButton(tr("Linear")); - linear_button->setProperty("type", EFFECT_KEYFRAME_LINEAR); - linear_button->setCheckable(true); - bezier_button = new QPushButton(tr("Bezier")); - bezier_button->setProperty("type", EFFECT_KEYFRAME_BEZIER); - bezier_button->setCheckable(true); - hold_button = new QPushButton(tr("Hold")); - hold_button->setProperty("type", EFFECT_KEYFRAME_HOLD); - hold_button->setCheckable(true); + linear_button = new QPushButton(); + linear_button->setProperty("type", EFFECT_KEYFRAME_LINEAR); + linear_button->setCheckable(true); + bezier_button = new QPushButton(); + bezier_button->setProperty("type", EFFECT_KEYFRAME_BEZIER); + bezier_button->setCheckable(true); + hold_button = new QPushButton(); + hold_button->setProperty("type", EFFECT_KEYFRAME_HOLD); + hold_button->setCheckable(true); - center_tool_layout->addStretch(); - center_tool_layout->addWidget(linear_button); - center_tool_layout->addWidget(bezier_button); - center_tool_layout->addWidget(hold_button); + center_tool_layout->addStretch(); + center_tool_layout->addWidget(linear_button); + center_tool_layout->addWidget(bezier_button); + center_tool_layout->addWidget(hold_button); - layout->addWidget(tool_widget); + layout->addWidget(tool_widget); - QWidget* central_widget = new QWidget(); - QVBoxLayout* central_layout = new QVBoxLayout(central_widget); - central_layout->setSpacing(0); - central_layout->setMargin(0); - header = new TimelineHeader(); - header->viewer = panel_sequence_viewer; - central_layout->addWidget(header); - view = new GraphView(); - central_layout->addWidget(view); + QWidget* central_widget = new QWidget(); + QVBoxLayout* central_layout = new QVBoxLayout(central_widget); + central_layout->setSpacing(0); + central_layout->setMargin(0); + header = new TimelineHeader(); + header->viewer = panel_sequence_viewer; + central_layout->addWidget(header); + view = new GraphView(); + central_layout->addWidget(view); - layout->addWidget(central_widget); + layout->addWidget(central_widget); - QWidget* value_widget = new QWidget(); - value_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); - QHBoxLayout* values = new QHBoxLayout(value_widget); - values->addStretch(); + QWidget* value_widget = new QWidget(); + value_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); + QHBoxLayout* values = new QHBoxLayout(value_widget); + values->addStretch(); - QWidget* central_value_widget = new QWidget(); - value_layout = new QHBoxLayout(central_value_widget); - value_layout->setMargin(0); - value_layout->addWidget(new QLabel("")); // a spacer so the layout doesn't jump - values->addWidget(central_value_widget); + QWidget* central_value_widget = new QWidget(); + value_layout = new QHBoxLayout(central_value_widget); + value_layout->setMargin(0); + value_layout->addWidget(new QLabel("")); // a spacer so the layout doesn't jump + values->addWidget(central_value_widget); - values->addStretch(); - layout->addWidget(value_widget); + values->addStretch(); + layout->addWidget(value_widget); - current_row_desc = new QLabel(); - current_row_desc->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); - current_row_desc->setAlignment(Qt::AlignCenter); - layout->addWidget(current_row_desc); + current_row_desc = new QLabel(); + current_row_desc->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); + current_row_desc->setAlignment(Qt::AlignCenter); + layout->addWidget(current_row_desc); - connect(view, SIGNAL(zoom_changed(double, double)), header, SLOT(update_zoom(double))); - connect(view, SIGNAL(x_scroll_changed(int)), header, SLOT(set_scroll(int))); - connect(view, SIGNAL(selection_changed(bool, int)), this, SLOT(set_key_button_enabled(bool, int))); + connect(view, SIGNAL(zoom_changed(double, double)), header, SLOT(update_zoom(double))); + connect(view, SIGNAL(x_scroll_changed(int)), header, SLOT(set_scroll(int))); + connect(view, SIGNAL(selection_changed(bool, int)), this, SLOT(set_key_button_enabled(bool, int))); - connect(linear_button, SIGNAL(clicked(bool)), this, SLOT(set_keyframe_type())); - connect(bezier_button, SIGNAL(clicked(bool)), this, SLOT(set_keyframe_type())); - connect(hold_button, SIGNAL(clicked(bool)), this, SLOT(set_keyframe_type())); + connect(linear_button, SIGNAL(clicked(bool)), this, SLOT(set_keyframe_type())); + connect(bezier_button, SIGNAL(clicked(bool)), this, SLOT(set_keyframe_type())); + connect(hold_button, SIGNAL(clicked(bool)), this, SLOT(set_keyframe_type())); + + Retranslate(); +} + +void GraphEditor::Retranslate() { + setWindowTitle(tr("Graph Editor")); + linear_button->setText(tr("Linear")); + bezier_button->setText(tr("Bezier")); + hold_button->setText(tr("Hold")); } void GraphEditor::update_panel() { - if (isVisible()) { - if (row != nullptr) { - int slider_index = 0; - for (int i=0;ifieldCount();i++) { - EffectField* field = row->field(i); - if (field->type == EFFECT_FIELD_DOUBLE) { - slider_proxies.at(slider_index)->set_value(row->field(i)->get_current_data().toDouble(), false); - slider_index++; - } - } - } + if (isVisible()) { + if (row != nullptr) { + int slider_index = 0; + for (int i=0;ifieldCount();i++) { + EffectField* field = row->field(i); + if (field->type == EFFECT_FIELD_DOUBLE) { + slider_proxies.at(slider_index)->set_value(row->field(i)->get_current_data().toDouble(), false); + slider_index++; + } + } + } - header->update(); - view->update(); - } + header->update(); + view->update(); + } } void GraphEditor::set_row(EffectRow *r) { - for (int i=0;iisKeyframing()) { - for (int i=0;ifieldCount();i++) { - EffectField* field = r->field(i); - if (field->type == EFFECT_FIELD_DOUBLE) { - QPushButton* slider_button = new QPushButton(); - slider_button->setCheckable(true); - slider_button->setChecked(field->is_enabled()); - slider_button->setIcon(QIcon(":/icons/record.png")); - slider_button->setProperty("field", i); - slider_button->setIconSize(slider_button->iconSize()*0.5); - connect(slider_button, SIGNAL(toggled(bool)), this, SLOT(set_field_visibility(bool))); - slider_proxy_buttons.append(slider_button); - value_layout->addWidget(slider_button); + if (r != nullptr && r->isKeyframing()) { + for (int i=0;ifieldCount();i++) { + EffectField* field = r->field(i); + if (field->type == EFFECT_FIELD_DOUBLE) { + QPushButton* slider_button = new QPushButton(); + slider_button->setCheckable(true); + slider_button->setChecked(field->is_enabled()); + slider_button->setIcon(QIcon(":/icons/record.png")); + slider_button->setProperty("field", i); + slider_button->setIconSize(slider_button->iconSize()*0.5); + connect(slider_button, SIGNAL(toggled(bool)), this, SLOT(set_field_visibility(bool))); + slider_proxy_buttons.append(slider_button); + value_layout->addWidget(slider_button); - LabelSlider* slider = new LabelSlider(); - slider->set_color(get_curve_color(i, r->fieldCount()).name()); - connect(slider, SIGNAL(valueChanged()), this, SLOT(passthrough_slider_value())); - slider_proxies.append(slider); - value_layout->addWidget(slider); + LabelSlider* slider = new LabelSlider(); + slider->set_color(get_curve_color(i, r->fieldCount()).name()); + connect(slider, SIGNAL(valueChanged()), this, SLOT(passthrough_slider_value())); + slider_proxies.append(slider); + value_layout->addWidget(slider); - slider_proxy_sources.append(static_cast(field->ui_element)); + slider_proxy_sources.append(static_cast(field->ui_element)); - found_vals = true; - } - } - } + found_vals = true; + } + } + } - if (found_vals) { - row = r; - current_row_desc->setText(row->parent_effect->parent_clip->name + " :: " + row->parent_effect->meta->name + " :: " + row->get_name()); - header->set_visible_in(r->parent_effect->parent_clip->timeline_in); + if (found_vals) { + row = r; + current_row_desc->setText(row->parent_effect->parent_clip->name + " :: " + row->parent_effect->meta->name + " :: " + row->get_name()); + header->set_visible_in(r->parent_effect->parent_clip->timeline_in); - connect(keyframe_nav, SIGNAL(goto_previous_key()), row, SLOT(goto_previous_key())); - connect(keyframe_nav, SIGNAL(toggle_key()), row, SLOT(toggle_key())); - connect(keyframe_nav, SIGNAL(goto_next_key()), row, SLOT(goto_next_key())); - } else { - row = nullptr; - current_row_desc->setText(nullptr); - } - view->set_row(row); - update_panel(); + connect(keyframe_nav, SIGNAL(goto_previous_key()), row, SLOT(goto_previous_key())); + connect(keyframe_nav, SIGNAL(toggle_key()), row, SLOT(toggle_key())); + connect(keyframe_nav, SIGNAL(goto_next_key()), row, SLOT(goto_next_key())); + } else { + row = nullptr; + current_row_desc->setText(nullptr); + } + view->set_row(row); + update_panel(); } bool GraphEditor::view_is_focused() { - return view->hasFocus() || header->hasFocus(); + return view->hasFocus() || header->hasFocus(); } bool GraphEditor::view_is_under_mouse() { - return view->underMouse() || header->underMouse(); + return view->underMouse() || header->underMouse(); } void GraphEditor::delete_selected_keys() { - view->delete_selected_keys(); + view->delete_selected_keys(); } void GraphEditor::select_all() { - view->select_all(); + view->select_all(); } void GraphEditor::set_key_button_enabled(bool e, int type) { - linear_button->setEnabled(e); - linear_button->setChecked(type == EFFECT_KEYFRAME_LINEAR); - bezier_button->setEnabled(e); - bezier_button->setChecked(type == EFFECT_KEYFRAME_BEZIER); - hold_button->setEnabled(e); - hold_button->setChecked(type == EFFECT_KEYFRAME_HOLD); + linear_button->setEnabled(e); + linear_button->setChecked(type == EFFECT_KEYFRAME_LINEAR); + bezier_button->setEnabled(e); + bezier_button->setChecked(type == EFFECT_KEYFRAME_BEZIER); + hold_button->setEnabled(e); + hold_button->setChecked(type == EFFECT_KEYFRAME_HOLD); } void GraphEditor::passthrough_slider_value() { - for (int i=0;iset_value(slider_proxies.at(i)->value(), true); - } - } + for (int i=0;iset_value(slider_proxies.at(i)->value(), true); + } + } } void GraphEditor::set_keyframe_type() { - linear_button->setChecked(linear_button == sender()); - bezier_button->setChecked(bezier_button == sender()); - hold_button->setChecked(hold_button == sender()); - view->set_selected_keyframe_type(sender()->property("type").toInt()); + linear_button->setChecked(linear_button == sender()); + bezier_button->setChecked(bezier_button == sender()); + hold_button->setChecked(hold_button == sender()); + view->set_selected_keyframe_type(sender()->property("type").toInt()); } void GraphEditor::set_field_visibility(bool b) { - view->set_field_visibility(sender()->property("field").toInt(), b); + view->set_field_visibility(sender()->property("field").toInt(), b); } diff --git a/panels/grapheditor.h b/panels/grapheditor.h index 4b22e9d9f..5a6eea0a2 100644 --- a/panels/grapheditor.h +++ b/panels/grapheditor.h @@ -21,45 +21,48 @@ #ifndef GRAPHEDITOR_H #define GRAPHEDITOR_H -#include #include #include #include +#include "ui/panel.h" #include "ui/graphview.h" #include "ui/timelineheader.h" #include "ui/labelslider.h" #include "ui/keyframenavigator.h" #include "project/effectrow.h" -class GraphEditor : public QDockWidget { - Q_OBJECT +class GraphEditor : public Panel { + Q_OBJECT public: - GraphEditor(QWidget* parent = nullptr); - void update_panel(); - void set_row(EffectRow* r); - bool view_is_focused(); - bool view_is_under_mouse(); - void delete_selected_keys(); - void select_all(); + GraphEditor(QWidget* parent = nullptr); + + void update_panel(); + void set_row(EffectRow* r); + bool view_is_focused(); + bool view_is_under_mouse(); + void delete_selected_keys(); + void select_all(); +protected: + virtual void Retranslate() override; private: - GraphView* view; - TimelineHeader* header; - QHBoxLayout* value_layout; - QVector slider_proxies; - QVector slider_proxy_buttons; - QVector slider_proxy_sources; - QLabel* current_row_desc; - EffectRow* row; - KeyframeNavigator* keyframe_nav; - QPushButton* linear_button; - QPushButton* bezier_button; - QPushButton* hold_button; + GraphView* view; + TimelineHeader* header; + QHBoxLayout* value_layout; + QVector slider_proxies; + QVector slider_proxy_buttons; + QVector slider_proxy_sources; + QLabel* current_row_desc; + EffectRow* row; + KeyframeNavigator* keyframe_nav; + QPushButton* linear_button; + QPushButton* bezier_button; + QPushButton* hold_button; private slots: - void set_key_button_enabled(bool e, int type); - void passthrough_slider_value(); - void set_keyframe_type(); - void set_field_visibility(bool b); + void set_key_button_enabled(bool e, int type); + void passthrough_slider_value(); + void set_keyframe_type(); + void set_field_visibility(bool b); }; #endif // GRAPHEDITOR_H diff --git a/panels/panels.cpp b/panels/panels.cpp index 0bc9bf83a..5a6794ed5 100644 --- a/panels/panels.cpp +++ b/panels/panels.cpp @@ -39,175 +39,175 @@ Timeline* panel_timeline = nullptr; GraphEditor* panel_graph_editor = nullptr; void update_effect_controls() { - // SEND CLIPS TO EFFECT CONTROLS - // find out how many clips are selected - // limits to one video clip and one audio clip and only if they're linked - // one of these days it might be nice to have multiple clips in the effects panel - bool multiple = false; - int vclip = -1; - int aclip = -1; - QVector selected_clips; - int mode = kTransitionNone; - if (olive::ActiveSequence != nullptr) { - for (int i=0;iclips.size();i++) { - ClipPtr clip = olive::ActiveSequence->clips.at(i); - if (clip != nullptr) { - for (int j=0;jselections.size();j++) { - const Selection& s = olive::ActiveSequence->selections.at(j); - bool add = true; - if (clip->timeline_in >= s.in && clip->timeline_out <= s.out && clip->track == s.track) { - mode = kTransitionNone; - } else if (selection_contains_transition(s, clip, kTransitionOpening)) { - mode = kTransitionOpening; - } else if (selection_contains_transition(s, clip, kTransitionClosing)) { - mode = kTransitionClosing; - } else { - add = false; - } + // SEND CLIPS TO EFFECT CONTROLS + // find out how many clips are selected + // limits to one video clip and one audio clip and only if they're linked + // one of these days it might be nice to have multiple clips in the effects panel + bool multiple = false; + int vclip = -1; + int aclip = -1; + QVector selected_clips; + int mode = kTransitionNone; + if (olive::ActiveSequence != nullptr) { + for (int i=0;iclips.size();i++) { + ClipPtr clip = olive::ActiveSequence->clips.at(i); + if (clip != nullptr) { + for (int j=0;jselections.size();j++) { + const Selection& s = olive::ActiveSequence->selections.at(j); + bool add = true; + if (clip->timeline_in >= s.in && clip->timeline_out <= s.out && clip->track == s.track) { + mode = kTransitionNone; + } else if (selection_contains_transition(s, clip, kTransitionOpening)) { + mode = kTransitionOpening; + } else if (selection_contains_transition(s, clip, kTransitionClosing)) { + mode = kTransitionClosing; + } else { + add = false; + } - if (add) { - if (clip->track < 0 && vclip == -1) { - vclip = i; - } else if (clip->track >= 0 && aclip == -1) { - aclip = i; - } else { - vclip = -2; - aclip = -2; - multiple = true; - multiple = true; - break; - } - } - } - } - } + if (add) { + if (clip->track < 0 && vclip == -1) { + vclip = i; + } else if (clip->track >= 0 && aclip == -1) { + aclip = i; + } else { + vclip = -2; + aclip = -2; + multiple = true; + multiple = true; + break; + } + } + } + } + } - if (!multiple) { - // check if aclip is linked to vclip - if (vclip >= 0) selected_clips.append(vclip); - if (aclip >= 0) selected_clips.append(aclip); - if (vclip >= 0 && aclip >= 0) { - bool found = false; - ClipPtr vclip_ref = olive::ActiveSequence->clips.at(vclip); - for (int i=0;ilinked.size();i++) { - if (vclip_ref->linked.at(i) == aclip) { - found = true; - break; - } - } - if (!found) { - // only display multiple clips if they're linked - selected_clips.clear(); - multiple = true; - } - } - } - } + if (!multiple) { + // check if aclip is linked to vclip + if (vclip >= 0) selected_clips.append(vclip); + if (aclip >= 0) selected_clips.append(aclip); + if (vclip >= 0 && aclip >= 0) { + bool found = false; + ClipPtr vclip_ref = olive::ActiveSequence->clips.at(vclip); + for (int i=0;ilinked.size();i++) { + if (vclip_ref->linked.at(i) == aclip) { + found = true; + break; + } + } + if (!found) { + // only display multiple clips if they're linked + selected_clips.clear(); + multiple = true; + } + } + } + } - bool same = (selected_clips.size() == panel_effect_controls->selected_clips.size() - && panel_effect_controls->get_mode() == mode); - if (same) { - for (int i=0;iselected_clips.at(i)) { - same = false; - break; - } - } - } + bool same = (selected_clips.size() == panel_effect_controls->selected_clips.size() + && panel_effect_controls->get_mode() == mode); + if (same) { + for (int i=0;iselected_clips.at(i)) { + same = false; + break; + } + } + } - if (panel_effect_controls->multiple != multiple || !same) { - panel_effect_controls->multiple = multiple; + if (panel_effect_controls->multiple != multiple || !same) { + panel_effect_controls->multiple = multiple; - panel_effect_controls->set_clips(selected_clips, mode); - } + panel_effect_controls->set_clips(selected_clips, mode); + } } void update_ui(bool modified) { - if (modified) { - update_effect_controls(); - } - panel_effect_controls->update_keyframes(); - panel_timeline->repaint_timeline(); - panel_sequence_viewer->update_viewer(); - panel_graph_editor->update_panel(); + if (modified) { + update_effect_controls(); + } + panel_effect_controls->update_keyframes(); + panel_timeline->repaint_timeline(); + panel_sequence_viewer->update_viewer(); + panel_graph_editor->update_panel(); } QDockWidget *get_focused_panel(bool force_hover) { - QDockWidget* w = nullptr; - if (olive::CurrentConfig.hover_focus || force_hover) { - if (panel_project->underMouse()) { - w = panel_project; - } else if (panel_effect_controls->underMouse()) { - w = panel_effect_controls; - } else if (panel_sequence_viewer->underMouse()) { - w = panel_sequence_viewer; - } else if (panel_footage_viewer->underMouse()) { - w = panel_footage_viewer; - } else if (panel_timeline->underMouse()) { - w = panel_timeline; - } else if (panel_graph_editor->view_is_under_mouse()) { - w = panel_graph_editor; - } - } - if (w == nullptr) { - if (panel_project->is_focused()) { - w = panel_project; - } else if (panel_effect_controls->keyframe_focus() || panel_effect_controls->is_focused()) { - w = panel_effect_controls; - } else if (panel_sequence_viewer->is_focused()) { - w = panel_sequence_viewer; - } else if (panel_footage_viewer->is_focused()) { - w = panel_footage_viewer; - } else if (panel_timeline->focused()) { - w = panel_timeline; - } else if (panel_graph_editor->view_is_focused()) { - w = panel_graph_editor; - } - } - return w; + QDockWidget* w = nullptr; + if (olive::CurrentConfig.hover_focus || force_hover) { + if (panel_project->underMouse()) { + w = panel_project; + } else if (panel_effect_controls->underMouse()) { + w = panel_effect_controls; + } else if (panel_sequence_viewer->underMouse()) { + w = panel_sequence_viewer; + } else if (panel_footage_viewer->underMouse()) { + w = panel_footage_viewer; + } else if (panel_timeline->underMouse()) { + w = panel_timeline; + } else if (panel_graph_editor->view_is_under_mouse()) { + w = panel_graph_editor; + } + } + if (w == nullptr) { + if (panel_project->is_focused()) { + w = panel_project; + } else if (panel_effect_controls->keyframe_focus() || panel_effect_controls->is_focused()) { + w = panel_effect_controls; + } else if (panel_sequence_viewer->is_focused()) { + w = panel_sequence_viewer; + } else if (panel_footage_viewer->is_focused()) { + w = panel_footage_viewer; + } else if (panel_timeline->focused()) { + w = panel_timeline; + } else if (panel_graph_editor->view_is_focused()) { + w = panel_graph_editor; + } + } + return w; } void alloc_panels(QWidget* parent) { - // TODO maybe replace these with non-pointers later on? - panel_sequence_viewer = new Viewer(parent); - panel_sequence_viewer->setObjectName("seq_viewer"); - panel_sequence_viewer->set_panel_name(QCoreApplication::translate("Viewer", "Sequence Viewer")); - panel_footage_viewer = new Viewer(parent); - panel_footage_viewer->setObjectName("footage_viewer"); - panel_footage_viewer->set_panel_name(QCoreApplication::translate("Viewer", "Media Viewer")); - panel_project = new Project(parent); - panel_project->setObjectName("proj_root"); - panel_effect_controls = new EffectControls(parent); - init_effects(); - panel_effect_controls->setObjectName("fx_controls"); - panel_timeline = new Timeline(parent); - panel_timeline->setObjectName("timeline"); - panel_graph_editor = new GraphEditor(parent); - panel_graph_editor->setObjectName("graph_editor"); + // TODO maybe replace these with non-pointers later on? + panel_sequence_viewer = new Viewer(parent); + panel_sequence_viewer->setObjectName("seq_viewer"); + panel_sequence_viewer->set_panel_name(QCoreApplication::translate("Viewer", "Sequence Viewer")); + panel_footage_viewer = new Viewer(parent); + panel_footage_viewer->setObjectName("footage_viewer"); + panel_footage_viewer->set_panel_name(QCoreApplication::translate("Viewer", "Media Viewer")); + panel_project = new Project(parent); + panel_project->setObjectName("proj_root"); + panel_effect_controls = new EffectControls(parent); + init_effects(); + panel_effect_controls->setObjectName("fx_controls"); + panel_timeline = new Timeline(parent); + panel_timeline->setObjectName("timeline"); + panel_graph_editor = new GraphEditor(parent); + panel_graph_editor->setObjectName("graph_editor"); } void free_panels() { - delete panel_sequence_viewer; - panel_sequence_viewer = nullptr; - delete panel_footage_viewer; - panel_footage_viewer = nullptr; - delete panel_project; - panel_project = nullptr; - delete panel_effect_controls; - panel_effect_controls = nullptr; - delete panel_timeline; - panel_timeline = nullptr; + delete panel_sequence_viewer; + panel_sequence_viewer = nullptr; + delete panel_footage_viewer; + panel_footage_viewer = nullptr; + delete panel_project; + panel_project = nullptr; + delete panel_effect_controls; + panel_effect_controls = nullptr; + delete panel_timeline; + panel_timeline = nullptr; } void scroll_to_frame_internal(QScrollBar* bar, long frame, double zoom, int area_width) { - int screen_point = getScreenPointFromFrame(zoom, frame) - bar->value(); - int min_x = area_width*0.1; - int max_x = area_width-min_x; - if (screen_point < min_x) { - bar->setValue(getScreenPointFromFrame(zoom, frame) - min_x); - } else if (screen_point > max_x) { - bar->setValue(getScreenPointFromFrame(zoom, frame) - max_x); - } + int screen_point = getScreenPointFromFrame(zoom, frame) - bar->value(); + int min_x = area_width*0.1; + int max_x = area_width-min_x; + if (screen_point < min_x) { + bar->setValue(getScreenPointFromFrame(zoom, frame) - min_x); + } else if (screen_point > max_x) { + bar->setValue(getScreenPointFromFrame(zoom, frame) - max_x); + } } diff --git a/panels/project.cpp b/panels/project.cpp index 34c7ff843..58d1b6324 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -60,8 +60,8 @@ #include extern "C" { - #include - #include +#include +#include } #define MAXIMUM_RECENT_PROJECTS 10 // FIXME: should be configurable @@ -70,1265 +70,1269 @@ QString autorecovery_filename; QStringList recent_projects; Project::Project(QWidget *parent) : - QDockWidget(parent) + Panel(parent) { - setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - QWidget* dockWidgetContents = new QWidget(this); + QWidget* dockWidgetContents = new QWidget(this); - QVBoxLayout* verticalLayout = new QVBoxLayout(dockWidgetContents); - verticalLayout->setMargin(0); - verticalLayout->setSpacing(0); + QVBoxLayout* verticalLayout = new QVBoxLayout(dockWidgetContents); + verticalLayout->setMargin(0); + verticalLayout->setSpacing(0); - setWidget(dockWidgetContents); + setWidget(dockWidgetContents); - sources_common = new SourcesCommon(this); + sources_common = new SourcesCommon(this); - sorter = new ProjectFilter(this); - sorter->setSourceModel(&olive::project_model); + sorter = new ProjectFilter(this); + sorter->setSourceModel(&olive::project_model); - // optional toolbar - toolbar_widget = new QWidget(); - toolbar_widget->setVisible(olive::CurrentConfig.show_project_toolbar); - toolbar_widget->setObjectName("project_toolbar"); + // optional toolbar + toolbar_widget = new QWidget(); + toolbar_widget->setVisible(olive::CurrentConfig.show_project_toolbar); + toolbar_widget->setObjectName("project_toolbar"); - QHBoxLayout* toolbar = new QHBoxLayout(toolbar_widget); - toolbar->setMargin(0); - toolbar->setSpacing(0); + QHBoxLayout* toolbar = new QHBoxLayout(toolbar_widget); + toolbar->setMargin(0); + toolbar->setSpacing(0); - QPushButton* toolbar_new = new QPushButton(); - QIcon icon1; - icon1.addFile(QStringLiteral(":/icons/add-button.png"), QSize(), QIcon::Normal, QIcon::On); - icon1.addFile(QStringLiteral(":/icons/add-button-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); - toolbar_new->setIcon(icon1); - toolbar_new->setToolTip("New"); - connect(toolbar_new, SIGNAL(clicked(bool)), this, SLOT(make_new_menu())); - toolbar->addWidget(toolbar_new); + QPushButton* toolbar_new = new QPushButton(); + QIcon icon1; + icon1.addFile(QStringLiteral(":/icons/add-button.png"), QSize(), QIcon::Normal, QIcon::On); + icon1.addFile(QStringLiteral(":/icons/add-button-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); + toolbar_new->setIcon(icon1); + toolbar_new->setToolTip("New"); + connect(toolbar_new, SIGNAL(clicked(bool)), this, SLOT(make_new_menu())); + toolbar->addWidget(toolbar_new); - QPushButton* toolbar_open = new QPushButton(); - QIcon icon2; - icon2.addFile(QStringLiteral(":/icons/open.png"), QSize(), QIcon::Normal, QIcon::On); - icon2.addFile(QStringLiteral(":/icons/open-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); - toolbar_open->setIcon(icon2); - toolbar_open->setToolTip("Open Project"); - connect(toolbar_open, SIGNAL(clicked(bool)), olive::Global.get(), SLOT(open_project())); - toolbar->addWidget(toolbar_open); + QPushButton* toolbar_open = new QPushButton(); + QIcon icon2; + icon2.addFile(QStringLiteral(":/icons/open.png"), QSize(), QIcon::Normal, QIcon::On); + icon2.addFile(QStringLiteral(":/icons/open-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); + toolbar_open->setIcon(icon2); + toolbar_open->setToolTip("Open Project"); + connect(toolbar_open, SIGNAL(clicked(bool)), olive::Global.get(), SLOT(open_project())); + toolbar->addWidget(toolbar_open); - QPushButton* toolbar_save = new QPushButton(); - QIcon icon3; - icon3.addFile(QStringLiteral(":/icons/save.png"), QSize(), QIcon::Normal, QIcon::On); - icon3.addFile(QStringLiteral(":/icons/save-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); - toolbar_save->setIcon(icon3); - toolbar_save->setToolTip("Save Project"); - connect(toolbar_save, SIGNAL(clicked(bool)), olive::Global.get(), SLOT(save_project())); - toolbar->addWidget(toolbar_save); + QPushButton* toolbar_save = new QPushButton(); + QIcon icon3; + icon3.addFile(QStringLiteral(":/icons/save.png"), QSize(), QIcon::Normal, QIcon::On); + icon3.addFile(QStringLiteral(":/icons/save-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); + toolbar_save->setIcon(icon3); + toolbar_save->setToolTip("Save Project"); + connect(toolbar_save, SIGNAL(clicked(bool)), olive::Global.get(), SLOT(save_project())); + toolbar->addWidget(toolbar_save); - QPushButton* toolbar_undo = new QPushButton(); - QIcon icon4; - icon4.addFile(QStringLiteral(":/icons/undo.png"), QSize(), QIcon::Normal, QIcon::On); - icon4.addFile(QStringLiteral(":/icons/undo-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); - toolbar_undo->setIcon(icon4); - toolbar_undo->setToolTip("Undo"); - connect(toolbar_undo, SIGNAL(clicked(bool)), olive::Global.get(), SLOT(undo())); - toolbar->addWidget(toolbar_undo); + QPushButton* toolbar_undo = new QPushButton(); + QIcon icon4; + icon4.addFile(QStringLiteral(":/icons/undo.png"), QSize(), QIcon::Normal, QIcon::On); + icon4.addFile(QStringLiteral(":/icons/undo-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); + toolbar_undo->setIcon(icon4); + toolbar_undo->setToolTip("Undo"); + connect(toolbar_undo, SIGNAL(clicked(bool)), olive::Global.get(), SLOT(undo())); + toolbar->addWidget(toolbar_undo); - QPushButton* toolbar_redo = new QPushButton(); - QIcon icon5; - icon5.addFile(QStringLiteral(":/icons/redo.png"), QSize(), QIcon::Normal, QIcon::On); - icon5.addFile(QStringLiteral(":/icons/redo-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); - toolbar_redo->setIcon(icon5); - toolbar_redo->setToolTip("Redo"); - connect(toolbar_redo, SIGNAL(clicked(bool)), olive::Global.get(), SLOT(redo())); - toolbar->addWidget(toolbar_redo); + QPushButton* toolbar_redo = new QPushButton(); + QIcon icon5; + icon5.addFile(QStringLiteral(":/icons/redo.png"), QSize(), QIcon::Normal, QIcon::On); + icon5.addFile(QStringLiteral(":/icons/redo-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); + toolbar_redo->setIcon(icon5); + toolbar_redo->setToolTip("Redo"); + connect(toolbar_redo, SIGNAL(clicked(bool)), olive::Global.get(), SLOT(redo())); + toolbar->addWidget(toolbar_redo); - QLineEdit* toolbar_search = new QLineEdit(); - toolbar_search->setClearButtonEnabled(true); - toolbar_search->setPlaceholderText(tr("Search media, markers, etc.")); - connect(toolbar_search, SIGNAL(textChanged(QString)), sorter, SLOT(update_search_filter(const QString&))); - toolbar->addWidget(toolbar_search); + toolbar_search = new QLineEdit(); + toolbar_search->setClearButtonEnabled(true); + connect(toolbar_search, SIGNAL(textChanged(QString)), sorter, SLOT(update_search_filter(const QString&))); + toolbar->addWidget(toolbar_search); - QPushButton* toolbar_tree_view = new QPushButton(); - QIcon icon6; - icon6.addFile(QStringLiteral(":/icons/treeview.png"), QSize(), QIcon::Normal, QIcon::On); - icon6.addFile(QStringLiteral(":/icons/treeview-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); - toolbar_tree_view->setIcon(icon6); - toolbar_tree_view->setToolTip("Tree View"); - connect(toolbar_tree_view, SIGNAL(clicked(bool)), this, SLOT(set_tree_view())); - toolbar->addWidget(toolbar_tree_view); + QPushButton* toolbar_tree_view = new QPushButton(); + QIcon icon6; + icon6.addFile(QStringLiteral(":/icons/treeview.png"), QSize(), QIcon::Normal, QIcon::On); + icon6.addFile(QStringLiteral(":/icons/treeview-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); + toolbar_tree_view->setIcon(icon6); + toolbar_tree_view->setToolTip("Tree View"); + connect(toolbar_tree_view, SIGNAL(clicked(bool)), this, SLOT(set_tree_view())); + toolbar->addWidget(toolbar_tree_view); - QPushButton* toolbar_icon_view = new QPushButton(); - QIcon icon7; - icon7.addFile(QStringLiteral(":/icons/iconview.png"), QSize(), QIcon::Normal, QIcon::On); - icon7.addFile(QStringLiteral(":/icons/iconview-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); - toolbar_icon_view->setIcon(icon7); - toolbar_icon_view->setToolTip("Icon View"); - connect(toolbar_icon_view, SIGNAL(clicked(bool)), this, SLOT(set_icon_view())); - toolbar->addWidget(toolbar_icon_view); + QPushButton* toolbar_icon_view = new QPushButton(); + QIcon icon7; + icon7.addFile(QStringLiteral(":/icons/iconview.png"), QSize(), QIcon::Normal, QIcon::On); + icon7.addFile(QStringLiteral(":/icons/iconview-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); + toolbar_icon_view->setIcon(icon7); + toolbar_icon_view->setToolTip("Icon View"); + connect(toolbar_icon_view, SIGNAL(clicked(bool)), this, SLOT(set_icon_view())); + toolbar->addWidget(toolbar_icon_view); - verticalLayout->addWidget(toolbar_widget); + verticalLayout->addWidget(toolbar_widget); - // tree view - tree_view = new SourceTable(); - tree_view->project_parent = this; - tree_view->setModel(sorter); - verticalLayout->addWidget(tree_view); + // tree view + tree_view = new SourceTable(); + tree_view->project_parent = this; + tree_view->setModel(sorter); + verticalLayout->addWidget(tree_view); - // Set the first column width - // I'm not sure if there's a better way to do this, default behavior seems to have all columns fixed width - // and let the last column fill up the remainder when really the opposite would be preferable (having the - // first column fill up the majority of the space). Anyway, this will probably do for now. - tree_view->setColumnWidth(0, tree_view->width()/2); + // Set the first column width + // I'm not sure if there's a better way to do this, default behavior seems to have all columns fixed width + // and let the last column fill up the remainder when really the opposite would be preferable (having the + // first column fill up the majority of the space). Anyway, this will probably do for now. + tree_view->setColumnWidth(0, tree_view->width()/2); - // icon view - icon_view_container = new QWidget(); + // icon view + icon_view_container = new QWidget(); - QVBoxLayout* icon_view_container_layout = new QVBoxLayout(icon_view_container); - icon_view_container_layout->setMargin(0); - icon_view_container_layout->setSpacing(0); + QVBoxLayout* icon_view_container_layout = new QVBoxLayout(icon_view_container); + icon_view_container_layout->setMargin(0); + icon_view_container_layout->setSpacing(0); - QHBoxLayout* icon_view_controls = new QHBoxLayout(); - icon_view_controls->setMargin(0); - icon_view_controls->setSpacing(0); + QHBoxLayout* icon_view_controls = new QHBoxLayout(); + icon_view_controls->setMargin(0); + icon_view_controls->setSpacing(0); - QIcon directory_up_button; - directory_up_button.addFile(":/icons/dirup.png", QSize(), QIcon::Normal); - directory_up_button.addFile(":/icons/dirup-disabled.png", QSize(), QIcon::Disabled); + QIcon directory_up_button; + directory_up_button.addFile(":/icons/dirup.png", QSize(), QIcon::Normal); + directory_up_button.addFile(":/icons/dirup-disabled.png", QSize(), QIcon::Disabled); - directory_up = new QPushButton(); - directory_up->setIcon(directory_up_button); - directory_up->setEnabled(false); - icon_view_controls->addWidget(directory_up); + directory_up = new QPushButton(); + directory_up->setIcon(directory_up_button); + directory_up->setEnabled(false); + icon_view_controls->addWidget(directory_up); - icon_view_controls->addStretch(); + icon_view_controls->addStretch(); - QSlider* icon_size_slider = new QSlider(Qt::Horizontal); - icon_size_slider->setMinimum(16); - icon_size_slider->setMaximum(120); - icon_view_controls->addWidget(icon_size_slider); - connect(icon_size_slider, SIGNAL(valueChanged(int)), this, SLOT(set_icon_view_size(int))); + QSlider* icon_size_slider = new QSlider(Qt::Horizontal); + icon_size_slider->setMinimum(16); + icon_size_slider->setMaximum(120); + icon_view_controls->addWidget(icon_size_slider); + connect(icon_size_slider, SIGNAL(valueChanged(int)), this, SLOT(set_icon_view_size(int))); - icon_view_container_layout->addLayout(icon_view_controls); + icon_view_container_layout->addLayout(icon_view_controls); - icon_view = new SourceIconView(); - icon_view->project_parent = this; - icon_view->setModel(sorter); - icon_view->setIconSize(QSize(100, 100)); - icon_view->setViewMode(QListView::IconMode); - icon_view->setUniformItemSizes(true); - icon_view_container_layout->addWidget(icon_view); + icon_view = new SourceIconView(); + icon_view->project_parent = this; + icon_view->setModel(sorter); + icon_view->setIconSize(QSize(100, 100)); + icon_view->setViewMode(QListView::IconMode); + icon_view->setUniformItemSizes(true); + icon_view_container_layout->addWidget(icon_view); - icon_size_slider->setValue(icon_view->iconSize().height()); + icon_size_slider->setValue(icon_view->iconSize().height()); - verticalLayout->addWidget(icon_view_container); + verticalLayout->addWidget(icon_view_container); - connect(directory_up, SIGNAL(clicked(bool)), this, SLOT(go_up_dir())); - connect(icon_view, SIGNAL(changed_root()), this, SLOT(set_up_dir_enabled())); + connect(directory_up, SIGNAL(clicked(bool)), this, SLOT(go_up_dir())); + connect(icon_view, SIGNAL(changed_root()), this, SLOT(set_up_dir_enabled())); - setWindowTitle(tr("Project")); + update_view_type(); - update_view_type(); + Retranslate(); } Project::~Project() { - delete sorter; + delete sorter; +} + +void Project::Retranslate() { + toolbar_search->setPlaceholderText(tr("Search media, markers, etc.")); + setWindowTitle(tr("Project")); } QString Project::get_next_sequence_name(QString start) { - if (start.isEmpty()) start = tr("Sequence"); + if (start.isEmpty()) start = tr("Sequence"); - int n = 1; - bool found = true; - QString name; - while (found) { - found = false; - name = start + " "; - if (n < 10) { - name += "0"; - } - name += QString::number(n); - for (int i=0;iget_name(), name, Qt::CaseInsensitive) == 0) { - found = true; - n++; - break; - } - } - } - return name; + int n = 1; + bool found = true; + QString name; + while (found) { + found = false; + name = start + " "; + if (n < 10) { + name += "0"; + } + name += QString::number(n); + for (int i=0;iget_name(), name, Qt::CaseInsensitive) == 0) { + found = true; + n++; + break; + } + } + } + return name; } SequencePtr create_sequence_from_media(QVector& media_list) { - SequencePtr s(new Sequence()); + SequencePtr s(new Sequence()); - s->name = panel_project->get_next_sequence_name(); + s->name = panel_project->get_next_sequence_name(); - // shitty hardcoded default values - s->width = 1920; - s->height = 1080; - s->frame_rate = 29.97; - s->audio_frequency = 48000; - s->audio_layout = 3; + // shitty hardcoded default values + s->width = 1920; + s->height = 1080; + s->frame_rate = 29.97; + s->audio_frequency = 48000; + s->audio_layout = 3; - bool got_video_values = false; - bool got_audio_values = false; - for (int i=0;iget_type()) { - case MEDIA_TYPE_FOOTAGE: - { - FootagePtr m = media->to_footage(); - if (m->ready) { - if (!got_video_values) { - for (int j=0;jvideo_tracks.size();j++) { - const FootageStream& ms = m->video_tracks.at(j); - s->width = ms.video_width; - s->height = ms.video_height; - if (!qFuzzyCompare(ms.video_frame_rate, 0.0)) { - s->frame_rate = ms.video_frame_rate * m->speed; + bool got_video_values = false; + bool got_audio_values = false; + for (int i=0;iget_type()) { + case MEDIA_TYPE_FOOTAGE: + { + FootagePtr m = media->to_footage(); + if (m->ready) { + if (!got_video_values) { + for (int j=0;jvideo_tracks.size();j++) { + const FootageStream& ms = m->video_tracks.at(j); + s->width = ms.video_width; + s->height = ms.video_height; + if (!qFuzzyCompare(ms.video_frame_rate, 0.0)) { + s->frame_rate = ms.video_frame_rate * m->speed; - if (ms.video_interlacing != VIDEO_PROGRESSIVE) s->frame_rate *= 2; + if (ms.video_interlacing != VIDEO_PROGRESSIVE) s->frame_rate *= 2; - // only break with a decent frame rate, otherwise there may be a better candidate - got_video_values = true; - break; - } - } - } - if (!got_audio_values && m->audio_tracks.size() > 0) { - const FootageStream& ms = m->audio_tracks.at(0); - s->audio_frequency = ms.audio_frequency; - got_audio_values = true; - } - } - } - break; - case MEDIA_TYPE_SEQUENCE: - { - SequencePtr seq = media->to_sequence(); - s->width = seq->width; - s->height = seq->height; - s->frame_rate = seq->frame_rate; - s->audio_frequency = seq->audio_frequency; - s->audio_layout = seq->audio_layout; + // only break with a decent frame rate, otherwise there may be a better candidate + got_video_values = true; + break; + } + } + } + if (!got_audio_values && m->audio_tracks.size() > 0) { + const FootageStream& ms = m->audio_tracks.at(0); + s->audio_frequency = ms.audio_frequency; + got_audio_values = true; + } + } + } + break; + case MEDIA_TYPE_SEQUENCE: + { + SequencePtr seq = media->to_sequence(); + s->width = seq->width; + s->height = seq->height; + s->frame_rate = seq->frame_rate; + s->audio_frequency = seq->audio_frequency; + s->audio_layout = seq->audio_layout; - got_video_values = true; - got_audio_values = true; - } - break; - } - if (got_video_values && got_audio_values) break; - } + got_video_values = true; + got_audio_values = true; + } + break; + } + if (got_video_values && got_audio_values) break; + } - return s; + return s; } void Project::duplicate_selected() { - QModelIndexList items = get_current_selected(); - bool duped = false; - ComboAction* ca = new ComboAction(); - for (int j=0;jget_type() == MEDIA_TYPE_SEQUENCE) { - create_sequence_internal(ca, i->to_sequence()->copy(), false, item_to_media(items.at(j).parent())); - duped = true; - } - } - if (duped) { - olive::UndoStack.push(ca); - } else { - delete ca; - } + QModelIndexList items = get_current_selected(); + bool duped = false; + ComboAction* ca = new ComboAction(); + for (int j=0;jget_type() == MEDIA_TYPE_SEQUENCE) { + create_sequence_internal(ca, i->to_sequence()->copy(), false, item_to_media(items.at(j).parent())); + duped = true; + } + } + if (duped) { + olive::UndoStack.push(ca); + } else { + delete ca; + } } void Project::replace_selected_file() { - QModelIndexList selected_items = get_current_selected(); - if (selected_items.size() == 1) { - Media* item = item_to_media(selected_items.at(0)); - if (item->get_type() == MEDIA_TYPE_FOOTAGE) { - replace_media(item, nullptr); - } - } + QModelIndexList selected_items = get_current_selected(); + if (selected_items.size() == 1) { + Media* item = item_to_media(selected_items.at(0)); + if (item->get_type() == MEDIA_TYPE_FOOTAGE) { + replace_media(item, nullptr); + } + } } void Project::replace_media(Media* item, QString filename) { - if (filename.isEmpty()) { - filename = QFileDialog::getOpenFileName( - this, - tr("Replace '%1'").arg(item->get_name()), - "", - tr("All Files") + " (*)"); - } - if (!filename.isEmpty()) { - ReplaceMediaCommand* rmc = new ReplaceMediaCommand(item, filename); - olive::UndoStack.push(rmc); - } + if (filename.isEmpty()) { + filename = QFileDialog::getOpenFileName( + this, + tr("Replace '%1'").arg(item->get_name()), + "", + tr("All Files") + " (*)"); + } + if (!filename.isEmpty()) { + ReplaceMediaCommand* rmc = new ReplaceMediaCommand(item, filename); + olive::UndoStack.push(rmc); + } } void Project::replace_clip_media() { - if (olive::ActiveSequence == nullptr) { - QMessageBox::critical(this, - tr("No active sequence"), - tr("No sequence is active, please open the sequence you want to replace clips from."), - QMessageBox::Ok); - } else { - QModelIndexList selected_items = get_current_selected(); - if (selected_items.size() == 1) { - Media* item = item_to_media(selected_items.at(0)); - if (item->get_type() == MEDIA_TYPE_SEQUENCE && olive::ActiveSequence == item->to_sequence()) { - QMessageBox::critical(this, - tr("Active sequence selected"), - tr("You cannot insert a sequence into itself, so no clips of this media would be in this sequence."), - QMessageBox::Ok); - } else { - ReplaceClipMediaDialog dialog(this, item); - dialog.exec(); - } - } - } + if (olive::ActiveSequence == nullptr) { + QMessageBox::critical(this, + tr("No active sequence"), + tr("No sequence is active, please open the sequence you want to replace clips from."), + QMessageBox::Ok); + } else { + QModelIndexList selected_items = get_current_selected(); + if (selected_items.size() == 1) { + Media* item = item_to_media(selected_items.at(0)); + if (item->get_type() == MEDIA_TYPE_SEQUENCE && olive::ActiveSequence == item->to_sequence()) { + QMessageBox::critical(this, + tr("Active sequence selected"), + tr("You cannot insert a sequence into itself, so no clips of this media would be in this sequence."), + QMessageBox::Ok); + } else { + ReplaceClipMediaDialog dialog(this, item); + dialog.exec(); + } + } + } } void Project::open_properties() { - QModelIndexList selected_items = get_current_selected(); - if (selected_items.size() == 1) { - Media* item = item_to_media(selected_items.at(0)); - switch (item->get_type()) { - case MEDIA_TYPE_FOOTAGE: - { - MediaPropertiesDialog mpd(this, item); - mpd.exec(); - } - break; - case MEDIA_TYPE_SEQUENCE: - { - NewSequenceDialog nsd(this, item); - nsd.exec(); - } - break; - default: - { - // fall back to renaming - QString new_name = QInputDialog::getText(this, - tr("Rename '%1'").arg(item->get_name()), - tr("Enter new name:"), - QLineEdit::Normal, - item->get_name()); - if (!new_name.isEmpty()) { - MediaRename* mr = new MediaRename(item, new_name); - olive::UndoStack.push(mr); - } - } - } + QModelIndexList selected_items = get_current_selected(); + if (selected_items.size() == 1) { + Media* item = item_to_media(selected_items.at(0)); + switch (item->get_type()) { + case MEDIA_TYPE_FOOTAGE: + { + MediaPropertiesDialog mpd(this, item); + mpd.exec(); } + break; + case MEDIA_TYPE_SEQUENCE: + { + NewSequenceDialog nsd(this, item); + nsd.exec(); + } + break; + default: + { + // fall back to renaming + QString new_name = QInputDialog::getText(this, + tr("Rename '%1'").arg(item->get_name()), + tr("Enter new name:"), + QLineEdit::Normal, + item->get_name()); + if (!new_name.isEmpty()) { + MediaRename* mr = new MediaRename(item, new_name); + olive::UndoStack.push(mr); + } + } + } + } } void Project::new_folder() { - Media* m = create_folder_internal(nullptr); - olive::UndoStack.push(new AddMediaCommand(m, get_selected_folder())); + Media* m = create_folder_internal(nullptr); + olive::UndoStack.push(new AddMediaCommand(m, get_selected_folder())); - QModelIndex index = olive::project_model.create_index(m->row(), 0, m); - switch (olive::CurrentConfig.project_view_type) { - case PROJECT_VIEW_TREE: - tree_view->edit(sorter->mapFromSource(index)); - break; - case PROJECT_VIEW_ICON: - icon_view->edit(sorter->mapFromSource(index)); - break; - } + QModelIndex index = olive::project_model.create_index(m->row(), 0, m); + switch (olive::CurrentConfig.project_view_type) { + case PROJECT_VIEW_TREE: + tree_view->edit(sorter->mapFromSource(index)); + break; + case PROJECT_VIEW_ICON: + icon_view->edit(sorter->mapFromSource(index)); + break; + } } void Project::new_sequence() { - NewSequenceDialog nsd(this); - nsd.set_sequence_name(get_next_sequence_name()); - nsd.exec(); + NewSequenceDialog nsd(this); + nsd.set_sequence_name(get_next_sequence_name()); + nsd.exec(); } Media* Project::create_sequence_internal(ComboAction *ca, SequencePtr s, bool open, Media* parent) { - if (parent == nullptr) { - parent = olive::project_model.get_root(); + if (parent == nullptr) { + parent = olive::project_model.get_root(); + } + + Media* item(new Media(parent)); + item->set_sequence(s); + + if (ca != nullptr) { + ca->append(new NewSequenceCommand(item, parent)); + if (open) ca->append(new ChangeSequenceAction(s)); + } else { + if (parent == olive::project_model.get_root()) { + olive::project_model.appendChild(parent, item); + } else { + parent->appendChild(item); } - - Media* item(new Media(parent)); - item->set_sequence(s); - - if (ca != nullptr) { - ca->append(new NewSequenceCommand(item, parent)); - if (open) ca->append(new ChangeSequenceAction(s)); - } else { - if (parent == olive::project_model.get_root()) { - olive::project_model.appendChild(parent, item); - } else { - parent->appendChild(item); - } - if (open) set_sequence(s); - } - return item; + if (open) set_sequence(s); + } + return item; } QString Project::get_file_name_from_path(const QString& path) { - return path.mid(path.lastIndexOf('/')+1); + return path.mid(path.lastIndexOf('/')+1); } /*Media* Project::new_item() { Media* item = new Media(0); - //item->setFlags(item->flags() | Qt::ItemIsEditable); - return item; + //item->setFlags(item->flags() | Qt::ItemIsEditable); + return item; }*/ bool Project::is_focused() { - return tree_view->hasFocus() || icon_view->hasFocus(); + return tree_view->hasFocus() || icon_view->hasFocus(); } Media* Project::create_folder_internal(QString name) { - Media* item = new Media(nullptr); - item->set_folder(); - item->set_name(name); - return item; + Media* item = new Media(nullptr); + item->set_folder(); + item->set_name(name); + return item; } Media *Project::item_to_media(const QModelIndex &index) { - return static_cast(sorter->mapToSource(index).internalPointer()); -// return static_cast(index.internalPointer()); + return static_cast(sorter->mapToSource(index).internalPointer()); + // return static_cast(index.internalPointer()); } void Project::get_all_media_from_table(QList& items, QList& list, int search_type) { - for (int i=0;iget_type() == MEDIA_TYPE_FOLDER) { - QList children; - for (int j=0;jchildCount();j++) { - children.append(item->child(j)); - } - get_all_media_from_table(children, list, search_type); - } else if (search_type == item->get_type() || search_type == -1) { - list.append(item); - } - } + for (int i=0;iget_type() == MEDIA_TYPE_FOLDER) { + QList children; + for (int j=0;jchildCount();j++) { + children.append(item->child(j)); + } + get_all_media_from_table(children, list, search_type); + } else if (search_type == item->get_type() || search_type == -1) { + list.append(item); + } + } } bool delete_clips_in_clipboard_with_media(ComboAction* ca, Media* m) { - int delete_count = 0; - if (clipboard_type == CLIPBOARD_TYPE_CLIP) { - for (int i=0;i(clipboard.at(i)); - if (c->media == m) { - ca->append(new RemoveClipsFromClipboard(i-delete_count)); - delete_count++; - } - } - } - return (delete_count > 0); + int delete_count = 0; + if (clipboard_type == CLIPBOARD_TYPE_CLIP) { + for (int i=0;i(clipboard.at(i)); + if (c->media == m) { + ca->append(new RemoveClipsFromClipboard(i-delete_count)); + delete_count++; + } + } + } + return (delete_count > 0); } void Project::delete_selected_media() { - ComboAction* ca = new ComboAction(); - QModelIndexList selected_items = get_current_selected(); - QList items; - for (int i=0;i items; + for (int i=0;i parents; - QList sequence_items; - QList all_top_level_items; - for (int i=0;i 0) { - QList media_items; - get_all_media_from_table(items, media_items, MEDIA_TYPE_FOOTAGE); - for (int i=0;ito_footage(); - bool confirm_delete = false; - for (int j=0;jto_sequence(); - for (int k=0;kclips.size();k++) { - ClipPtr c = s->clips.at(k); - if (c != nullptr && c->media == item) { - if (!confirm_delete) { - // we found a reference, so we know we'll need to ask if the user wants to delete it - QMessageBox confirm(this); - confirm.setWindowTitle(tr("Delete media in use?")); - confirm.setText(tr("The media '%1' is currently used in '%2'. Deleting it will remove all instances in the sequence. Are you sure you want to do this?").arg(media->name, s->name)); - QAbstractButton* yes_button = confirm.addButton(QMessageBox::Yes); - QAbstractButton* skip_button = nullptr; - if (items.size() > 1) skip_button = confirm.addButton(tr("Skip"), QMessageBox::NoRole); - QAbstractButton* abort_button = confirm.addButton(QMessageBox::Cancel); - confirm.exec(); - if (confirm.clickedButton() == yes_button) { - // remove all clips referencing this media - confirm_delete = true; - redraw = true; - } else if (confirm.clickedButton() == skip_button) { - // remove media item and any folders containing it from the remove list - Media* parent = item; - while (parent != nullptr) { - parents.append(parent); + // check if media is in use + QVector parents; + QList sequence_items; + QList all_top_level_items; + for (int i=0;i 0) { + QList media_items; + get_all_media_from_table(items, media_items, MEDIA_TYPE_FOOTAGE); + for (int i=0;ito_footage(); + bool confirm_delete = false; + for (int j=0;jto_sequence(); + for (int k=0;kclips.size();k++) { + ClipPtr c = s->clips.at(k); + if (c != nullptr && c->media == item) { + if (!confirm_delete) { + // we found a reference, so we know we'll need to ask if the user wants to delete it + QMessageBox confirm(this); + confirm.setWindowTitle(tr("Delete media in use?")); + confirm.setText(tr("The media '%1' is currently used in '%2'. Deleting it will remove all instances in the sequence. Are you sure you want to do this?").arg(media->name, s->name)); + QAbstractButton* yes_button = confirm.addButton(QMessageBox::Yes); + QAbstractButton* skip_button = nullptr; + if (items.size() > 1) skip_button = confirm.addButton(tr("Skip"), QMessageBox::NoRole); + QAbstractButton* abort_button = confirm.addButton(QMessageBox::Cancel); + confirm.exec(); + if (confirm.clickedButton() == yes_button) { + // remove all clips referencing this media + confirm_delete = true; + redraw = true; + } else if (confirm.clickedButton() == skip_button) { + // remove media item and any folders containing it from the remove list + Media* parent = item; + while (parent != nullptr) { + parents.append(parent); - // re-add item's siblings - for (int m=0;mchildCount();m++) { - Media* child = parent->child(m); - bool found = false; - for (int n=0;nchildCount();m++) { + Media* child = parent->child(m); + bool found = false; + for (int n=0;nparentItem(); - } + parent = parent->parentItem(); + } - j = sequence_items.size(); - k = s->clips.size(); - } else if (confirm.clickedButton() == abort_button) { - // break out of loop - i = media_items.size(); - j = sequence_items.size(); - k = s->clips.size(); + j = sequence_items.size(); + k = s->clips.size(); + } else if (confirm.clickedButton() == abort_button) { + // break out of loop + i = media_items.size(); + j = sequence_items.size(); + k = s->clips.size(); - remove = false; - } - } - if (confirm_delete) { - ca->append(new DeleteClipAction(s, k)); - } - } - } - } - if (confirm_delete) { - delete_clips_in_clipboard_with_media(ca, item); - } - } - } + remove = false; + } + } + if (confirm_delete) { + ca->append(new DeleteClipAction(s, k)); + } + } + } + } + if (confirm_delete) { + delete_clips_in_clipboard_with_media(ca, item); + } + } + } - // remove - if (remove) { - panel_effect_controls->clear_effects(true); - if (olive::ActiveSequence != nullptr) olive::ActiveSequence->selections.clear(); + // remove + if (remove) { + panel_effect_controls->clear_effects(true); + if (olive::ActiveSequence != nullptr) olive::ActiveSequence->selections.clear(); - // remove media and parents - for (int m=0;mappend(new DeleteMediaCommand(items.at(i))); + for (int i=0;iappend(new DeleteMediaCommand(items.at(i))); - if (items.at(i)->get_type() == MEDIA_TYPE_SEQUENCE) { - redraw = true; + if (items.at(i)->get_type() == MEDIA_TYPE_SEQUENCE) { + redraw = true; - SequencePtr s = items.at(i)->to_sequence(); + SequencePtr s = items.at(i)->to_sequence(); - if (s == olive::ActiveSequence) { - ca->append(new ChangeSequenceAction(nullptr)); - } + if (s == olive::ActiveSequence) { + ca->append(new ChangeSequenceAction(nullptr)); + } - if (s == panel_footage_viewer->seq) { - panel_footage_viewer->set_media(nullptr); - } - } else if (items.at(i)->get_type() == MEDIA_TYPE_FOOTAGE) { - if (panel_footage_viewer->seq != nullptr) { - for (int j=0;jseq->clips.size();j++) { - ClipPtr c = panel_footage_viewer->seq->clips.at(j); - if (c != nullptr && c->media == items.at(i)) { - panel_footage_viewer->set_media(nullptr); - break; - } - } - } - } - } - olive::UndoStack.push(ca); + if (s == panel_footage_viewer->seq) { + panel_footage_viewer->set_media(nullptr); + } + } else if (items.at(i)->get_type() == MEDIA_TYPE_FOOTAGE) { + if (panel_footage_viewer->seq != nullptr) { + for (int j=0;jseq->clips.size();j++) { + ClipPtr c = panel_footage_viewer->seq->clips.at(j); + if (c != nullptr && c->media == items.at(i)) { + panel_footage_viewer->set_media(nullptr); + break; + } + } + } + } + } + olive::UndoStack.push(ca); - // redraw clips - if (redraw) { - update_ui(true); - } - } else { - delete ca; - } + // redraw clips + if (redraw) { + update_ui(true); + } + } else { + delete ca; + } } void Project::start_preview_generator(Media* item, bool replacing) { - // set up throbber animation - olive::media_icon_service->SetMediaIcon(item, ICON_TYPE_LOADING); + // set up throbber animation + olive::media_icon_service->SetMediaIcon(item, ICON_TYPE_LOADING); - PreviewGenerator* pg = new PreviewGenerator(item, item->to_footage(), replacing); - item->to_footage()->preview_gen = pg; - pg->start(QThread::LowPriority); + PreviewGenerator* pg = new PreviewGenerator(item, item->to_footage(), replacing); + item->to_footage()->preview_gen = pg; + pg->start(QThread::LowPriority); } void Project::process_file_list(QStringList& files, bool recursive, Media* replace, Media* parent) { - bool imported = false; + bool imported = false; - QVector image_sequence_urls; - QVector image_sequence_importassequence; - QStringList image_sequence_formats = olive::CurrentConfig.img_seq_formats.split("|"); + QVector image_sequence_urls; + QVector image_sequence_importassequence; + QStringList image_sequence_formats = olive::CurrentConfig.img_seq_formats.split("|"); - if (!recursive) last_imported_media.clear(); + if (!recursive) last_imported_media.clear(); - bool create_undo_action = (!recursive && replace == nullptr); - ComboAction* ca = nullptr; - if (create_undo_action) ca = new ComboAction(); + bool create_undo_action = (!recursive && replace == nullptr); + ComboAction* ca = nullptr; + if (create_undo_action) ca = new ComboAction(); - for (int i=0;iappend(new AddMediaCommand(folder, parent)); - } else { - olive::project_model.appendChild(parent, folder); - } + if (create_undo_action) { + ca->append(new AddMediaCommand(folder, parent)); + } else { + olive::project_model.appendChild(parent, folder); + } - imported = true; - } else if (!files.at(i).isEmpty()) { - QString file(files.at(i)); - bool skip = false; + imported = true; + } else if (!files.at(i).isEmpty()) { + QString file(files.at(i)); + bool skip = false; - /* Heuristic to determine whether file is part of an image sequence */ + /* Heuristic to determine whether file is part of an image sequence */ - // check file extension (assume it's not a + // check file extension (assume it's not a - int lastcharindex = file.lastIndexOf("."); - bool found = true; - if (lastcharindex != -1 && lastcharindex > file.lastIndexOf('/')) { - // image_sequence_formats - found = false; - QString ext = file.mid(lastcharindex+1); - for (int j=0;j file.lastIndexOf('/')) { + // image_sequence_formats + found = false; + QString ext = file.mid(lastcharindex+1); + for (int j=0;jto_footage(); - m->reset(); - } else { - item = new Media(parent); - m = FootagePtr(new Footage()); - } + if (replace != nullptr) { + item = replace; + m = replace->to_footage(); + m->reset(); + } else { + item = new Media(parent); + m = FootagePtr(new Footage()); + } - m->using_inout = false; - m->url = file; - m->name = get_file_name_from_path(files.at(i)); + m->using_inout = false; + m->url = file; + m->name = get_file_name_from_path(files.at(i)); - item->set_footage(m); + item->set_footage(m); - last_imported_media.append(item); + last_imported_media.append(item); - if (replace == nullptr) { - if (create_undo_action) { - ca->append(new AddMediaCommand(item, parent)); - } else { - parent->appendChild(item); -// project_model.appendChild(parent, item); - } - } + if (replace == nullptr) { + if (create_undo_action) { + ca->append(new AddMediaCommand(item, parent)); + } else { + parent->appendChild(item); + // project_model.appendChild(parent, item); + } + } - imported = true; - } - } - } - if (create_undo_action) { - if (imported) { - olive::UndoStack.push(ca); + imported = true; + } + } + } + if (create_undo_action) { + if (imported) { + olive::UndoStack.push(ca); - for (int i=0;iget_type() == MEDIA_TYPE_FOLDER) return m; - } - return nullptr; + // if one item is selected and it's a folder, return it + QModelIndexList selected_items = get_current_selected(); + if (selected_items.size() == 1) { + Media* m = item_to_media(selected_items.at(0)); + if (m->get_type() == MEDIA_TYPE_FOLDER) return m; + } + return nullptr; } bool Project::reveal_media(Media *media, QModelIndex parent) { - for (int i=0;iget_type() == MEDIA_TYPE_FOLDER) { + if (m->get_type() == MEDIA_TYPE_FOLDER) { - // if this item is a folder, recursively run this function to search it too - if (reveal_media(media, item)) return true; + // if this item is a folder, recursively run this function to search it too + if (reveal_media(media, item)) return true; - } else if (m == media) { - // if m == media, then we found the media object we were looking for + } else if (m == media) { + // if m == media, then we found the media object we were looking for - // get sorter proxy item (the item that's "visible") - QModelIndex sorted_index = sorter->mapFromSource(item); + // get sorter proxy item (the item that's "visible") + QModelIndex sorted_index = sorter->mapFromSource(item); - // retrieve its parent item - QModelIndex hierarchy = sorted_index.parent(); + // retrieve its parent item + QModelIndex hierarchy = sorted_index.parent(); - if (olive::CurrentConfig.project_view_type == PROJECT_VIEW_TREE) { + if (olive::CurrentConfig.project_view_type == PROJECT_VIEW_TREE) { - // if we're in tree view, expand every folder in the hierarchy containing the media - while (hierarchy.isValid()) { - tree_view->setExpanded(hierarchy, true); - hierarchy = hierarchy.parent(); - } + // if we're in tree view, expand every folder in the hierarchy containing the media + while (hierarchy.isValid()) { + tree_view->setExpanded(hierarchy, true); + hierarchy = hierarchy.parent(); + } - // select item (requires a QItemSelection object to select the whole row) - QItemSelection row_select( - sorter->index(sorted_index.row(), 0, sorted_index.parent()), - sorter->index(sorted_index.row(), sorter->columnCount()-1, sorted_index.parent()) - ); + // select item (requires a QItemSelection object to select the whole row) + QItemSelection row_select( + sorter->index(sorted_index.row(), 0, sorted_index.parent()), + sorter->index(sorted_index.row(), sorter->columnCount()-1, sorted_index.parent()) + ); - tree_view->selectionModel()->select(row_select, QItemSelectionModel::Select); - } else if (olive::CurrentConfig.project_view_type == PROJECT_VIEW_ICON) { + tree_view->selectionModel()->select(row_select, QItemSelectionModel::Select); + } else if (olive::CurrentConfig.project_view_type == PROJECT_VIEW_ICON) { - // if we're in icon view, we just "browse" to the parent folder - icon_view->setRootIndex(hierarchy); + // if we're in icon view, we just "browse" to the parent folder + icon_view->setRootIndex(hierarchy); - // select item in this folder - icon_view->selectionModel()->select(sorted_index, QItemSelectionModel::Select); + // select item in this folder + icon_view->selectionModel()->select(sorted_index, QItemSelectionModel::Select); - // update the "up" button state - set_up_dir_enabled(); + // update the "up" button state + set_up_dir_enabled(); - } + } - return true; - } - } + return true; + } + } - return false; + return false; } void Project::import_dialog() { - QFileDialog fd(this, tr("Import media..."), "", tr("All Files") + " (*)"); - fd.setFileMode(QFileDialog::ExistingFiles); + QFileDialog fd(this, tr("Import media..."), "", tr("All Files") + " (*)"); + fd.setFileMode(QFileDialog::ExistingFiles); - if (fd.exec()) { - QStringList files = fd.selectedFiles(); - process_file_list(files, false, nullptr, get_selected_folder()); - } + if (fd.exec()) { + QStringList files = fd.selectedFiles(); + process_file_list(files, false, nullptr, get_selected_folder()); + } } void Project::delete_clips_using_selected_media() { - if (olive::ActiveSequence == nullptr) { - QMessageBox::critical(this, - tr("No active sequence"), - tr("No sequence is active, please open the sequence you want to delete clips from."), - QMessageBox::Ok); - } else { - ComboAction* ca = new ComboAction(); - bool deleted = false; - QModelIndexList items = get_current_selected(); - for (int i=0;iclips.size();i++) { - const ClipPtr& c = olive::ActiveSequence->clips.at(i); - if (c != nullptr) { - for (int j=0;jmedia == m) { - ca->append(new DeleteClipAction(olive::ActiveSequence, i)); - deleted = true; - } - } - } - } - for (int j=0;jclips.size();i++) { + const ClipPtr& c = olive::ActiveSequence->clips.at(i); + if (c != nullptr) { + for (int j=0;jmedia == m) { + ca->append(new DeleteClipAction(olive::ActiveSequence, i)); + deleted = true; + } + } + } + } + for (int j=0;jclear_effects(true); + // clear effects cache + panel_effect_controls->clear_effects(true); - // delete sequences first because it's important to close all the clips before deleting the media - QVector sequences = list_all_project_sequences(); - for (int i=0;ito_sequence().reset(); - sequences.at(i)->set_sequence(nullptr); - } + // delete sequences first because it's important to close all the clips before deleting the media + QVector sequences = list_all_project_sequences(); + for (int i=0;ito_sequence().reset(); + sequences.at(i)->set_sequence(nullptr); + } - // delete everything else - olive::project_model.clear(); + // delete everything else + olive::project_model.clear(); - // update tree view (sometimes this doesn't seem to update reliably) - tree_view->update(); + // update tree view (sometimes this doesn't seem to update reliably) + tree_view->update(); } void Project::new_project() { - // clear existing project - set_sequence(nullptr); - panel_footage_viewer->set_media(nullptr); - clear(); - olive::MainWindow->setWindowModified(false); + // clear existing project + set_sequence(nullptr); + panel_footage_viewer->set_media(nullptr); + clear(); + olive::MainWindow->setWindowModified(false); } void Project::load_project(bool autorecovery) { - new_project(); + new_project(); - LoadDialog ld(this, autorecovery); - ld.exec(); + LoadDialog ld(this, autorecovery); + ld.exec(); } void save_marker(QXmlStreamWriter& stream, const Marker& m) { - stream.writeStartElement("marker"); - stream.writeAttribute("frame", QString::number(m.frame)); - stream.writeAttribute("name", m.name); - stream.writeEndElement(); + stream.writeStartElement("marker"); + stream.writeAttribute("frame", QString::number(m.frame)); + stream.writeAttribute("name", m.name); + stream.writeEndElement(); } void Project::save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only, const QModelIndex& parent) { - for (int i=0;iget_type()) { - if (m->get_type() == MEDIA_TYPE_FOLDER) { - if (set_ids_only) { - m->temp_id = folder_id; // saves a temporary ID for matching in the project file - folder_id++; - } else { - // if we're saving folders, save the folder - stream.writeStartElement("folder"); - stream.writeAttribute("name", m->get_name()); - stream.writeAttribute("id", QString::number(m->temp_id)); - if (!item.parent().isValid()) { - stream.writeAttribute("parent", "0"); - } else { - stream.writeAttribute("parent", QString::number(olive::project_model.getItem(item.parent())->temp_id)); - } - stream.writeEndElement(); - } - // save_folder(stream, item, type, set_ids_only); - } else { - int folder = m->parentItem()->temp_id; - if (type == MEDIA_TYPE_FOOTAGE) { - FootagePtr f = m->to_footage(); - f->save_id = media_id; - stream.writeStartElement("footage"); - stream.writeAttribute("id", QString::number(media_id)); - stream.writeAttribute("folder", QString::number(folder)); - stream.writeAttribute("name", f->name); - stream.writeAttribute("url", proj_dir.relativeFilePath(f->url)); - stream.writeAttribute("duration", QString::number(f->length)); - stream.writeAttribute("using_inout", QString::number(f->using_inout)); - stream.writeAttribute("in", QString::number(f->in)); - stream.writeAttribute("out", QString::number(f->out)); - stream.writeAttribute("speed", QString::number(f->speed)); - stream.writeAttribute("alphapremul", QString::number(f->alpha_is_premultiplied)); + if (type == m->get_type()) { + if (m->get_type() == MEDIA_TYPE_FOLDER) { + if (set_ids_only) { + m->temp_id = folder_id; // saves a temporary ID for matching in the project file + folder_id++; + } else { + // if we're saving folders, save the folder + stream.writeStartElement("folder"); + stream.writeAttribute("name", m->get_name()); + stream.writeAttribute("id", QString::number(m->temp_id)); + if (!item.parent().isValid()) { + stream.writeAttribute("parent", "0"); + } else { + stream.writeAttribute("parent", QString::number(olive::project_model.getItem(item.parent())->temp_id)); + } + stream.writeEndElement(); + } + // save_folder(stream, item, type, set_ids_only); + } else { + int folder = m->parentItem()->temp_id; + if (type == MEDIA_TYPE_FOOTAGE) { + FootagePtr f = m->to_footage(); + f->save_id = media_id; + stream.writeStartElement("footage"); + stream.writeAttribute("id", QString::number(media_id)); + stream.writeAttribute("folder", QString::number(folder)); + stream.writeAttribute("name", f->name); + stream.writeAttribute("url", proj_dir.relativeFilePath(f->url)); + stream.writeAttribute("duration", QString::number(f->length)); + stream.writeAttribute("using_inout", QString::number(f->using_inout)); + stream.writeAttribute("in", QString::number(f->in)); + stream.writeAttribute("out", QString::number(f->out)); + stream.writeAttribute("speed", QString::number(f->speed)); + stream.writeAttribute("alphapremul", QString::number(f->alpha_is_premultiplied)); - stream.writeAttribute("proxy", QString::number(f->proxy)); - stream.writeAttribute("proxypath", f->proxy_path); + stream.writeAttribute("proxy", QString::number(f->proxy)); + stream.writeAttribute("proxypath", f->proxy_path); - // save video stream metadata - for (int j=0;jvideo_tracks.size();j++) { - const FootageStream& ms = f->video_tracks.at(j); - stream.writeStartElement("video"); - stream.writeAttribute("id", QString::number(ms.file_index)); - stream.writeAttribute("width", QString::number(ms.video_width)); - stream.writeAttribute("height", QString::number(ms.video_height)); - stream.writeAttribute("framerate", QString::number(ms.video_frame_rate, 'f', 10)); - stream.writeAttribute("infinite", QString::number(ms.infinite_length)); - stream.writeEndElement(); // video - } + // save video stream metadata + for (int j=0;jvideo_tracks.size();j++) { + const FootageStream& ms = f->video_tracks.at(j); + stream.writeStartElement("video"); + stream.writeAttribute("id", QString::number(ms.file_index)); + stream.writeAttribute("width", QString::number(ms.video_width)); + stream.writeAttribute("height", QString::number(ms.video_height)); + stream.writeAttribute("framerate", QString::number(ms.video_frame_rate, 'f', 10)); + stream.writeAttribute("infinite", QString::number(ms.infinite_length)); + stream.writeEndElement(); // video + } - // save audio stream metadata - for (int j=0;jaudio_tracks.size();j++) { - const FootageStream& ms = f->audio_tracks.at(j); - stream.writeStartElement("audio"); - stream.writeAttribute("id", QString::number(ms.file_index)); - stream.writeAttribute("channels", QString::number(ms.audio_channels)); - stream.writeAttribute("layout", QString::number(ms.audio_layout)); - stream.writeAttribute("frequency", QString::number(ms.audio_frequency)); - stream.writeEndElement(); // audio - } + // save audio stream metadata + for (int j=0;jaudio_tracks.size();j++) { + const FootageStream& ms = f->audio_tracks.at(j); + stream.writeStartElement("audio"); + stream.writeAttribute("id", QString::number(ms.file_index)); + stream.writeAttribute("channels", QString::number(ms.audio_channels)); + stream.writeAttribute("layout", QString::number(ms.audio_layout)); + stream.writeAttribute("frequency", QString::number(ms.audio_frequency)); + stream.writeEndElement(); // audio + } - // save footage markers - for (int j=0;jmarkers.size();j++) { - save_marker(stream, f->markers.at(j)); - } + // save footage markers + for (int j=0;jmarkers.size();j++) { + save_marker(stream, f->markers.at(j)); + } - stream.writeEndElement(); // footage - media_id++; - } else if (type == MEDIA_TYPE_SEQUENCE) { - SequencePtr s = m->to_sequence(); - if (set_ids_only) { - s->save_id = sequence_id; - sequence_id++; - } else { - stream.writeStartElement("sequence"); - stream.writeAttribute("id", QString::number(s->save_id)); - stream.writeAttribute("folder", QString::number(folder)); - stream.writeAttribute("name", s->name); - stream.writeAttribute("width", QString::number(s->width)); - stream.writeAttribute("height", QString::number(s->height)); - stream.writeAttribute("framerate", QString::number(s->frame_rate, 'f', 10)); - stream.writeAttribute("afreq", QString::number(s->audio_frequency)); - stream.writeAttribute("alayout", QString::number(s->audio_layout)); - if (s == olive::ActiveSequence) { - stream.writeAttribute("open", "1"); - } - stream.writeAttribute("workarea", QString::number(s->using_workarea)); - stream.writeAttribute("workareaIn", QString::number(s->workarea_in)); - stream.writeAttribute("workareaOut", QString::number(s->workarea_out)); + stream.writeEndElement(); // footage + media_id++; + } else if (type == MEDIA_TYPE_SEQUENCE) { + SequencePtr s = m->to_sequence(); + if (set_ids_only) { + s->save_id = sequence_id; + sequence_id++; + } else { + stream.writeStartElement("sequence"); + stream.writeAttribute("id", QString::number(s->save_id)); + stream.writeAttribute("folder", QString::number(folder)); + stream.writeAttribute("name", s->name); + stream.writeAttribute("width", QString::number(s->width)); + stream.writeAttribute("height", QString::number(s->height)); + stream.writeAttribute("framerate", QString::number(s->frame_rate, 'f', 10)); + stream.writeAttribute("afreq", QString::number(s->audio_frequency)); + stream.writeAttribute("alayout", QString::number(s->audio_layout)); + if (s == olive::ActiveSequence) { + stream.writeAttribute("open", "1"); + } + stream.writeAttribute("workarea", QString::number(s->using_workarea)); + stream.writeAttribute("workareaIn", QString::number(s->workarea_in)); + stream.writeAttribute("workareaOut", QString::number(s->workarea_out)); - /* - for (int j=0;jtransitions.size();j++) { + /* + for (int j=0;jtransitions.size();j++) { TransitionPtr t = s->transitions.at(j); - if (t != nullptr) { - stream.writeStartElement("transition"); - stream.writeAttribute("id", QString::number(j)); - stream.writeAttribute("length", QString::number(t->get_true_length())); - t->save(stream); - stream.writeEndElement(); // transition - } - } + if (t != nullptr) { + stream.writeStartElement("transition"); + stream.writeAttribute("id", QString::number(j)); + stream.writeAttribute("length", QString::number(t->get_true_length())); + t->save(stream); + stream.writeEndElement(); // transition + } + } */ - for (int j=0;jclips.size();j++) { - const ClipPtr& c = s->clips.at(j); - if (c != nullptr) { - stream.writeStartElement("clip"); // clip - stream.writeAttribute("id", QString::number(j)); - stream.writeAttribute("enabled", QString::number(c->enabled)); - stream.writeAttribute("name", c->name); - stream.writeAttribute("clipin", QString::number(c->clip_in)); - stream.writeAttribute("in", QString::number(c->timeline_in)); - stream.writeAttribute("out", QString::number(c->timeline_out)); - stream.writeAttribute("track", QString::number(c->track)); + for (int j=0;jclips.size();j++) { + const ClipPtr& c = s->clips.at(j); + if (c != nullptr) { + stream.writeStartElement("clip"); // clip + stream.writeAttribute("id", QString::number(j)); + stream.writeAttribute("enabled", QString::number(c->enabled)); + stream.writeAttribute("name", c->name); + stream.writeAttribute("clipin", QString::number(c->clip_in)); + stream.writeAttribute("in", QString::number(c->timeline_in)); + stream.writeAttribute("out", QString::number(c->timeline_out)); + stream.writeAttribute("track", QString::number(c->track)); /* - stream.writeAttribute("opening", QString::number(c->opening_transition)); - stream.writeAttribute("closing", QString::number(c->closing_transition)); + stream.writeAttribute("opening", QString::number(c->opening_transition)); + stream.writeAttribute("closing", QString::number(c->closing_transition)); */ - stream.writeAttribute("r", QString::number(c->color_r)); - stream.writeAttribute("g", QString::number(c->color_g)); - stream.writeAttribute("b", QString::number(c->color_b)); + stream.writeAttribute("r", QString::number(c->color_r)); + stream.writeAttribute("g", QString::number(c->color_g)); + stream.writeAttribute("b", QString::number(c->color_b)); - stream.writeAttribute("autoscale", QString::number(c->autoscale)); - stream.writeAttribute("speed", QString::number(c->speed, 'f', 10)); - stream.writeAttribute("maintainpitch", QString::number(c->maintain_audio_pitch)); - stream.writeAttribute("reverse", QString::number(c->reverse)); + stream.writeAttribute("autoscale", QString::number(c->autoscale)); + stream.writeAttribute("speed", QString::number(c->speed, 'f', 10)); + stream.writeAttribute("maintainpitch", QString::number(c->maintain_audio_pitch)); + stream.writeAttribute("reverse", QString::number(c->reverse)); - if (c->media != nullptr) { - stream.writeAttribute("type", QString::number(c->media->get_type())); - switch (c->media->get_type()) { - case MEDIA_TYPE_FOOTAGE: - stream.writeAttribute("media", QString::number(c->media->to_footage()->save_id)); - stream.writeAttribute("stream", QString::number(c->media_stream)); - break; - case MEDIA_TYPE_SEQUENCE: - stream.writeAttribute("sequence", QString::number(c->media->to_sequence()->save_id)); - break; - } - } + if (c->media != nullptr) { + stream.writeAttribute("type", QString::number(c->media->get_type())); + switch (c->media->get_type()) { + case MEDIA_TYPE_FOOTAGE: + stream.writeAttribute("media", QString::number(c->media->to_footage()->save_id)); + stream.writeAttribute("stream", QString::number(c->media_stream)); + break; + case MEDIA_TYPE_SEQUENCE: + stream.writeAttribute("sequence", QString::number(c->media->to_sequence()->save_id)); + break; + } + } - // save markers - // only necessary for null media clips, since media has its own markers - if (c->media == nullptr) { - for (int k=0;kget_markers().size();k++) { - save_marker(stream, c->get_markers().at(k)); - } - } + // save markers + // only necessary for null media clips, since media has its own markers + if (c->media == nullptr) { + for (int k=0;kget_markers().size();k++) { + save_marker(stream, c->get_markers().at(k)); + } + } - // save clip links - stream.writeStartElement("linked"); // linked - for (int k=0;klinked.size();k++) { - stream.writeStartElement("link"); // link - stream.writeAttribute("id", QString::number(c->linked.at(k))); - stream.writeEndElement(); // link - } - stream.writeEndElement(); // linked + // save clip links + stream.writeStartElement("linked"); // linked + for (int k=0;klinked.size();k++) { + stream.writeStartElement("link"); // link + stream.writeAttribute("id", QString::number(c->linked.at(k))); + stream.writeEndElement(); // link + } + stream.writeEndElement(); // linked - for (int k=0;keffects.size();k++) { - stream.writeStartElement("effect"); // effect - c->effects.at(k)->save(stream); - stream.writeEndElement(); // effect - } + for (int k=0;keffects.size();k++) { + stream.writeStartElement("effect"); // effect + c->effects.at(k)->save(stream); + stream.writeEndElement(); // effect + } - stream.writeEndElement(); // clip - } - } - for (int j=0;jmarkers.size();j++) { - save_marker(stream, s->markers.at(j)); - } - stream.writeEndElement(); - } - } - } - } + stream.writeEndElement(); // clip + } + } + for (int j=0;jmarkers.size();j++) { + save_marker(stream, s->markers.at(j)); + } + stream.writeEndElement(); + } + } + } + } - if (m->get_type() == MEDIA_TYPE_FOLDER) { - save_folder(stream, type, set_ids_only, item); - } - } + if (m->get_type() == MEDIA_TYPE_FOLDER) { + save_folder(stream, type, set_ids_only, item); + } + } } void Project::save_project(bool autorecovery) { - folder_id = 1; - media_id = 1; - sequence_id = 1; + folder_id = 1; + media_id = 1; + sequence_id = 1; - QFile file(autorecovery ? autorecovery_filename : olive::ActiveProjectFilename); - if (!file.open(QIODevice::WriteOnly/* | QIODevice::Text*/)) { - qCritical() << "Could not open file"; - return; - } + QFile file(autorecovery ? autorecovery_filename : olive::ActiveProjectFilename); + if (!file.open(QIODevice::WriteOnly/* | QIODevice::Text*/)) { + qCritical() << "Could not open file"; + return; + } - QXmlStreamWriter stream(&file); - stream.setAutoFormatting(true); - stream.writeStartDocument(); // doc + QXmlStreamWriter stream(&file); + stream.setAutoFormatting(true); + stream.writeStartDocument(); // doc - stream.writeStartElement("project"); // project + stream.writeStartElement("project"); // project - stream.writeTextElement("version", QString::number(SAVE_VERSION)); + stream.writeTextElement("version", QString::number(SAVE_VERSION)); - stream.writeTextElement("url", olive::ActiveProjectFilename); - proj_dir = QFileInfo(olive::ActiveProjectFilename).absoluteDir(); + stream.writeTextElement("url", olive::ActiveProjectFilename); + proj_dir = QFileInfo(olive::ActiveProjectFilename).absoluteDir(); - save_folder(stream, MEDIA_TYPE_FOLDER, true); + save_folder(stream, MEDIA_TYPE_FOLDER, true); - stream.writeStartElement("folders"); // folders - save_folder(stream, MEDIA_TYPE_FOLDER, false); - stream.writeEndElement(); // folders + stream.writeStartElement("folders"); // folders + save_folder(stream, MEDIA_TYPE_FOLDER, false); + stream.writeEndElement(); // folders - stream.writeStartElement("media"); // media - save_folder(stream, MEDIA_TYPE_FOOTAGE, false); - stream.writeEndElement(); // media + stream.writeStartElement("media"); // media + save_folder(stream, MEDIA_TYPE_FOOTAGE, false); + stream.writeEndElement(); // media - save_folder(stream, MEDIA_TYPE_SEQUENCE, true); + save_folder(stream, MEDIA_TYPE_SEQUENCE, true); - stream.writeStartElement("sequences"); // sequences - save_folder(stream, MEDIA_TYPE_SEQUENCE, false); - stream.writeEndElement();// sequences + stream.writeStartElement("sequences"); // sequences + save_folder(stream, MEDIA_TYPE_SEQUENCE, false); + stream.writeEndElement();// sequences - stream.writeEndElement(); // project + stream.writeEndElement(); // project - stream.writeEndDocument(); // doc + stream.writeEndDocument(); // doc - file.close(); + file.close(); - if (!autorecovery) { - add_recent_project(olive::ActiveProjectFilename); - olive::MainWindow->setWindowModified(false); - } + if (!autorecovery) { + add_recent_project(olive::ActiveProjectFilename); + olive::MainWindow->setWindowModified(false); + } } void Project::update_view_type() { - tree_view->setVisible(olive::CurrentConfig.project_view_type == PROJECT_VIEW_TREE); - icon_view_container->setVisible(olive::CurrentConfig.project_view_type == PROJECT_VIEW_ICON); + tree_view->setVisible(olive::CurrentConfig.project_view_type == PROJECT_VIEW_TREE); + icon_view_container->setVisible(olive::CurrentConfig.project_view_type == PROJECT_VIEW_ICON); - switch (olive::CurrentConfig.project_view_type) { - case PROJECT_VIEW_TREE: - sources_common->view = tree_view; - break; - case PROJECT_VIEW_ICON: - sources_common->view = icon_view; - break; - } + switch (olive::CurrentConfig.project_view_type) { + case PROJECT_VIEW_TREE: + sources_common->view = tree_view; + break; + case PROJECT_VIEW_ICON: + sources_common->view = icon_view; + break; + } } void Project::set_icon_view() { - olive::CurrentConfig.project_view_type = PROJECT_VIEW_ICON; - update_view_type(); + olive::CurrentConfig.project_view_type = PROJECT_VIEW_ICON; + update_view_type(); } void Project::set_tree_view() { - olive::CurrentConfig.project_view_type = PROJECT_VIEW_TREE; - update_view_type(); + olive::CurrentConfig.project_view_type = PROJECT_VIEW_TREE; + update_view_type(); } void Project::save_recent_projects() { - // save to file - QFile f(olive::Global->get_recent_project_list_file()); - if (f.open(QFile::WriteOnly | QFile::Truncate | QFile::Text)) { - QTextStream out(&f); - for (int i=0;i 0) { - out << "\n"; - } - out << recent_projects.at(i); - } - f.close(); - } else { - qWarning() << "Could not save recent projects"; - } + // save to file + QFile f(olive::Global->get_recent_project_list_file()); + if (f.open(QFile::WriteOnly | QFile::Truncate | QFile::Text)) { + QTextStream out(&f); + for (int i=0;i 0) { + out << "\n"; + } + out << recent_projects.at(i); + } + f.close(); + } else { + qWarning() << "Could not save recent projects"; + } } void Project::clear_recent_projects() { - recent_projects.clear(); - save_recent_projects(); + recent_projects.clear(); + save_recent_projects(); } void Project::set_icon_view_size(int s) { - icon_view->setIconSize(QSize(s, s)); + icon_view->setIconSize(QSize(s, s)); } void Project::set_up_dir_enabled() { - directory_up->setEnabled(icon_view->rootIndex().isValid()); + directory_up->setEnabled(icon_view->rootIndex().isValid()); } void Project::go_up_dir() { - icon_view->setRootIndex(icon_view->rootIndex().parent()); - set_up_dir_enabled(); + icon_view->setRootIndex(icon_view->rootIndex().parent()); + set_up_dir_enabled(); } void Project::make_new_menu() { - QMenu new_menu(this); - olive::MenuHelper.make_new_menu(&new_menu); - new_menu.exec(QCursor::pos()); + QMenu new_menu(this); + olive::MenuHelper.make_new_menu(&new_menu); + new_menu.exec(QCursor::pos()); } void Project::add_recent_project(QString url) { - bool found = false; - for (int i=0;i MAXIMUM_RECENT_PROJECTS) { - recent_projects.removeLast(); - } - } - save_recent_projects(); + bool found = false; + for (int i=0;i MAXIMUM_RECENT_PROJECTS) { + recent_projects.removeLast(); + } + } + save_recent_projects(); } void Project::list_all_sequences_worker(QVector* list, Media* parent) { - for (int i=0;iget_type()) { - case MEDIA_TYPE_SEQUENCE: - list->append(item); - break; - case MEDIA_TYPE_FOLDER: - list_all_sequences_worker(list, item); - break; - } - } + for (int i=0;iget_type()) { + case MEDIA_TYPE_SEQUENCE: + list->append(item); + break; + case MEDIA_TYPE_FOLDER: + list_all_sequences_worker(list, item); + break; + } + } } QVector Project::list_all_project_sequences() { - QVector list; - list_all_sequences_worker(&list, nullptr); - return list; + QVector list; + list_all_sequences_worker(&list, nullptr); + return list; } QModelIndexList Project::get_current_selected() { - if (olive::CurrentConfig.project_view_type == PROJECT_VIEW_TREE) { - return tree_view->selectionModel()->selectedRows(); - } - return icon_view->selectionModel()->selectedIndexes(); + if (olive::CurrentConfig.project_view_type == PROJECT_VIEW_TREE) { + return tree_view->selectionModel()->selectedRows(); + } + return icon_view->selectionModel()->selectedIndexes(); } diff --git a/panels/project.h b/panels/project.h index 52113f290..5f80a5c46 100644 --- a/panels/project.h +++ b/panels/project.h @@ -21,7 +21,6 @@ #ifndef PROJECT_H #define PROJECT_H -#include #include #include #include @@ -35,6 +34,7 @@ #include "project/projectelements.h" #include "project/undo.h" #include "project/sourcescommon.h" +#include "ui/panel.h" #include "ui/sourceiconview.h" #include "ui/sourcetable.h" @@ -50,75 +50,79 @@ SequencePtr create_sequence_from_media(QVector &media_list); QString get_channel_layout_name(int channels, uint64_t layout); QString get_interlacing_name(int interlacing); -class Project : public QDockWidget { - Q_OBJECT +class Project : public Panel { + Q_OBJECT public: - explicit Project(QWidget *parent = nullptr); - ~Project(); - bool is_focused(); - void clear(); - Media* create_sequence_internal(ComboAction *ca, SequencePtr s, bool open, Media* parent); - QString get_next_sequence_name(QString start = nullptr); - void process_file_list(QStringList& files, bool recursive = false, Media* replace = nullptr, Media *parent = nullptr); - void replace_media(Media* item, QString filename); - Media* get_selected_folder(); - bool reveal_media(Media *media, QModelIndex parent = QModelIndex()); - void add_recent_project(QString url); + explicit Project(QWidget *parent = nullptr); + ~Project(); - void new_project(); - void load_project(bool autorecovery); - void save_project(bool autorecovery); + bool is_focused(); + void clear(); + Media* create_sequence_internal(ComboAction *ca, SequencePtr s, bool open, Media* parent); + QString get_next_sequence_name(QString start = nullptr); + void process_file_list(QStringList& files, bool recursive = false, Media* replace = nullptr, Media *parent = nullptr); + void replace_media(Media* item, QString filename); + Media* get_selected_folder(); + bool reveal_media(Media *media, QModelIndex parent = QModelIndex()); + void add_recent_project(QString url); - Media* create_folder_internal(QString name); - Media* item_to_media(const QModelIndex& index); + void new_project(); + void load_project(bool autorecovery); + void save_project(bool autorecovery); - void save_recent_projects(); + Media* create_folder_internal(QString name); + Media* item_to_media(const QModelIndex& index); - QVector list_all_project_sequences(); + void save_recent_projects(); - SourceTable* tree_view; - SourceIconView* icon_view; - SourcesCommon* sources_common; + QVector list_all_project_sequences(); - ProjectFilter* sorter; + SourceTable* tree_view; + SourceIconView* icon_view; + SourcesCommon* sources_common; - QVector last_imported_media; + ProjectFilter* sorter; - QModelIndexList get_current_selected(); + QVector last_imported_media; - void start_preview_generator(Media* item, bool replacing); - void get_all_media_from_table(QList &items, QList &list, int type = -1); + QModelIndexList get_current_selected(); - QWidget* toolbar_widget; + void start_preview_generator(Media* item, bool replacing); + void get_all_media_from_table(QList &items, QList &list, int type = -1); + + QWidget* toolbar_widget; +protected: + virtual void Retranslate() override; public slots: - void import_dialog(); - void delete_selected_media(); - void duplicate_selected(); - void delete_clips_using_selected_media(); - void replace_selected_file(); - void replace_clip_media(); - void open_properties(); - void new_folder(); - void new_sequence(); + void import_dialog(); + void delete_selected_media(); + void duplicate_selected(); + void delete_clips_using_selected_media(); + void replace_selected_file(); + void replace_clip_media(); + void open_properties(); + void new_folder(); + void new_sequence(); private: - void save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only, const QModelIndex &parent = QModelIndex()); - int folder_id; - int media_id; - int sequence_id; - void list_all_sequences_worker(QVector *list, Media* parent); - QString get_file_name_from_path(const QString &path); - QDir proj_dir; - QWidget* icon_view_container; - QPushButton* directory_up; + void save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only, const QModelIndex &parent = QModelIndex()); + int folder_id; + int media_id; + int sequence_id; + void list_all_sequences_worker(QVector *list, Media* parent); + QString get_file_name_from_path(const QString &path); + QDir proj_dir; + QWidget* icon_view_container; + QPushButton* directory_up; + QLineEdit* toolbar_search; private slots: - void update_view_type(); - void set_icon_view(); - void set_tree_view(); - void clear_recent_projects(); - void set_icon_view_size(int); - void set_up_dir_enabled(); - void go_up_dir(); - void make_new_menu(); + void update_view_type(); + void set_icon_view(); + void set_tree_view(); + void clear_recent_projects(); + void set_icon_view_size(int); + void set_up_dir_enabled(); + void go_up_dir(); + void make_new_menu(); }; #endif // PROJECT_H diff --git a/panels/timeline.cpp b/panels/timeline.cpp index b3fb23bb2..db7e23312 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -55,2044 +55,2055 @@ #include Timeline::Timeline(QWidget *parent) : - QDockWidget(parent), - cursor_frame(0), - cursor_track(0), - zoom(1.0), - zoom_just_changed(false), - showing_all(false), - snapping(true), - snapped(false), - snap_point(0), - selecting(false), - rect_select_init(false), - rect_select_proc(false), - moving_init(false), - moving_proc(false), - move_insert(false), - trim_target(-1), - trim_in_point(false), - splitting(false), - importing(false), - importing_files(false), - creating(false), - transition_tool_init(false), - transition_tool_proc(false), - transition_tool_pre_clip(-1), - transition_tool_post_clip(-1), - hand_moving(false), - block_repaints(false), - scroll(0) + Panel(parent), + cursor_frame(0), + cursor_track(0), + zoom(1.0), + zoom_just_changed(false), + showing_all(false), + snapping(true), + snapped(false), + snap_point(0), + selecting(false), + rect_select_init(false), + rect_select_proc(false), + moving_init(false), + moving_proc(false), + move_insert(false), + trim_target(-1), + trim_in_point(false), + splitting(false), + importing(false), + importing_files(false), + creating(false), + transition_tool_init(false), + transition_tool_proc(false), + transition_tool_pre_clip(-1), + transition_tool_post_clip(-1), + hand_moving(false), + block_repaints(false), + scroll(0) { - setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - setup_ui(); + setup_ui(); - default_track_height = qRound((QGuiApplication::primaryScreen()->logicalDotsPerInch() / 96) * TRACK_DEFAULT_HEIGHT); + default_track_height = qRound((QGuiApplication::primaryScreen()->logicalDotsPerInch() / 96) * TRACK_DEFAULT_HEIGHT); - headers->viewer = panel_sequence_viewer; + headers->viewer = panel_sequence_viewer; - video_area->bottom_align = true; - video_area->scrollBar = videoScrollbar; - audio_area->scrollBar = audioScrollbar; + video_area->bottom_align = true; + video_area->scrollBar = videoScrollbar; + audio_area->scrollBar = audioScrollbar; - tool_buttons.append(toolArrowButton); - tool_buttons.append(toolEditButton); - tool_buttons.append(toolRippleButton); - tool_buttons.append(toolRazorButton); - tool_buttons.append(toolSlipButton); - tool_buttons.append(toolSlideButton); - tool_buttons.append(toolTransitionButton); - tool_buttons.append(toolHandButton); + tool_buttons.append(toolArrowButton); + tool_buttons.append(toolEditButton); + tool_buttons.append(toolRippleButton); + tool_buttons.append(toolRazorButton); + tool_buttons.append(toolSlipButton); + tool_buttons.append(toolSlideButton); + tool_buttons.append(toolTransitionButton); + tool_buttons.append(toolHandButton); - toolArrowButton->click(); + toolArrowButton->click(); - connect(horizontalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(setScroll(int))); - connect(videoScrollbar, SIGNAL(valueChanged(int)), video_area, SLOT(setScroll(int))); - connect(audioScrollbar, SIGNAL(valueChanged(int)), audio_area, SLOT(setScroll(int))); - connect(horizontalScrollBar, SIGNAL(resize_move(double)), this, SLOT(resize_move(double))); + connect(horizontalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(setScroll(int))); + connect(videoScrollbar, SIGNAL(valueChanged(int)), video_area, SLOT(setScroll(int))); + connect(audioScrollbar, SIGNAL(valueChanged(int)), audio_area, SLOT(setScroll(int))); + connect(horizontalScrollBar, SIGNAL(resize_move(double)), this, SLOT(resize_move(double))); - update_sequence(); + update_sequence(); + + Retranslate(); } Timeline::~Timeline() {} +void Timeline::Retranslate() { + toolArrowButton->setToolTip(tr("Pointer Tool") + " (V)"); + toolEditButton->setToolTip(tr("Edit Tool") + " (X)"); + toolRippleButton->setToolTip(tr("Ripple Tool") + " (B)"); + toolRazorButton->setToolTip(tr("Razor Tool") + " (C)"); + toolSlipButton->setToolTip(tr("Slip Tool") + " (Y)"); + toolSlideButton->setToolTip(tr("Slide Tool") + " (U)"); + toolHandButton->setToolTip(tr("Hand Tool") + " (H)"); + toolTransitionButton->setToolTip(tr("Transition Tool") + " (T)"); + snappingButton->setToolTip(tr("Snapping") + " (S)"); + zoomInButton->setToolTip(tr("Zoom In") + " (=)"); + zoomOutButton->setToolTip(tr("Zoom Out") + " (-)"); + recordButton->setToolTip(tr("Record audio")); + addButton->setToolTip(tr("Add title, solid, bars, etc.")); + + UpdateTitle(); +} + void Timeline::previous_cut() { - if (olive::ActiveSequence != nullptr - && olive::ActiveSequence->playhead > 0) { - long p_cut = 0; - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr) { - if (c->timeline_out > p_cut && c->timeline_out < olive::ActiveSequence->playhead) { - p_cut = c->timeline_out; - } else if (c->timeline_in > p_cut && c->timeline_in < olive::ActiveSequence->playhead) { - p_cut = c->timeline_in; - } - } - } - panel_sequence_viewer->seek(p_cut); - } + if (olive::ActiveSequence != nullptr + && olive::ActiveSequence->playhead > 0) { + long p_cut = 0; + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr) { + if (c->timeline_out > p_cut && c->timeline_out < olive::ActiveSequence->playhead) { + p_cut = c->timeline_out; + } else if (c->timeline_in > p_cut && c->timeline_in < olive::ActiveSequence->playhead) { + p_cut = c->timeline_in; + } + } + } + panel_sequence_viewer->seek(p_cut); + } } void Timeline::next_cut() { - if (olive::ActiveSequence != nullptr) { - bool seek_enabled = false; - long n_cut = LONG_MAX; - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr) { - if (c->timeline_in < n_cut && c->timeline_in > olive::ActiveSequence->playhead) { - n_cut = c->timeline_in; - seek_enabled = true; - } else if (c->timeline_out < n_cut && c->timeline_out > olive::ActiveSequence->playhead) { - n_cut = c->timeline_out; - seek_enabled = true; - } - } + if (olive::ActiveSequence != nullptr) { + bool seek_enabled = false; + long n_cut = LONG_MAX; + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr) { + if (c->timeline_in < n_cut && c->timeline_in > olive::ActiveSequence->playhead) { + n_cut = c->timeline_in; + seek_enabled = true; + } else if (c->timeline_out < n_cut && c->timeline_out > olive::ActiveSequence->playhead) { + n_cut = c->timeline_out; + seek_enabled = true; } - if (seek_enabled) panel_sequence_viewer->seek(n_cut); + } } + if (seek_enabled) panel_sequence_viewer->seek(n_cut); + } } void ripple_clips(ComboAction* ca, SequencePtr s, long point, long length, const QVector& ignore) { - ca->append(new RippleAction(s, point, length, ignore)); + ca->append(new RippleAction(s, point, length, ignore)); } void Timeline::toggle_show_all() { - if (olive::ActiveSequence != nullptr) { - showing_all = !showing_all; - if (showing_all) { - old_zoom = zoom; - set_zoom_value(double(timeline_area->width() - 200) / double(olive::ActiveSequence->getEndFrame())); - } else { - set_zoom_value(old_zoom); - } - } + if (olive::ActiveSequence != nullptr) { + showing_all = !showing_all; + if (showing_all) { + old_zoom = zoom; + set_zoom_value(double(timeline_area->width() - 200) / double(olive::ActiveSequence->getEndFrame())); + } else { + set_zoom_value(old_zoom); + } + } } void Timeline::create_ghosts_from_media(SequencePtr seq, long entry_point, QVector& media_list) { - video_ghosts = false; - audio_ghosts = false; + video_ghosts = false; + audio_ghosts = false; - for (int i=0;iget_type()) { - case MEDIA_TYPE_FOOTAGE: - m = medium->to_footage(); - can_import = m->ready; - if (m->using_inout) { - double source_fr = 30; - if (m->video_tracks.size() > 0 && !qIsNull(m->video_tracks.at(0).video_frame_rate)) source_fr = m->video_tracks.at(0).video_frame_rate * m->speed; - default_clip_in = refactor_frame_number(m->in, source_fr, seq->frame_rate); - default_clip_out = refactor_frame_number(m->out, source_fr, seq->frame_rate); - } - break; - case MEDIA_TYPE_SEQUENCE: - s = medium->to_sequence(); - sequence_length = s->getEndFrame(); - if (seq != nullptr) sequence_length = refactor_frame_number(sequence_length, s->frame_rate, seq->frame_rate); - can_import = (s != seq && sequence_length != 0); - if (s->using_workarea) { - default_clip_in = refactor_frame_number(s->workarea_in, s->frame_rate, seq->frame_rate); - default_clip_out = refactor_frame_number(s->workarea_out, s->frame_rate, seq->frame_rate); - } - break; - default: - can_import = false; - } + switch (medium->get_type()) { + case MEDIA_TYPE_FOOTAGE: + m = medium->to_footage(); + can_import = m->ready; + if (m->using_inout) { + double source_fr = 30; + if (m->video_tracks.size() > 0 && !qIsNull(m->video_tracks.at(0).video_frame_rate)) source_fr = m->video_tracks.at(0).video_frame_rate * m->speed; + default_clip_in = refactor_frame_number(m->in, source_fr, seq->frame_rate); + default_clip_out = refactor_frame_number(m->out, source_fr, seq->frame_rate); + } + break; + case MEDIA_TYPE_SEQUENCE: + s = medium->to_sequence(); + sequence_length = s->getEndFrame(); + if (seq != nullptr) sequence_length = refactor_frame_number(sequence_length, s->frame_rate, seq->frame_rate); + can_import = (s != seq && sequence_length != 0); + if (s->using_workarea) { + default_clip_in = refactor_frame_number(s->workarea_in, s->frame_rate, seq->frame_rate); + default_clip_out = refactor_frame_number(s->workarea_out, s->frame_rate, seq->frame_rate); + } + break; + default: + can_import = false; + } - if (can_import) { - Ghost g; - g.clip = -1; - g.trimming = false; - g.old_clip_in = g.clip_in = default_clip_in; - g.media = medium; - g.in = entry_point; - g.transition = nullptr; + if (can_import) { + Ghost g; + g.clip = -1; + g.trimming = false; + g.old_clip_in = g.clip_in = default_clip_in; + g.media = medium; + g.in = entry_point; + g.transition = nullptr; - switch (medium->get_type()) { - case MEDIA_TYPE_FOOTAGE: - // is video source a still image? - if (m->video_tracks.size() > 0 && m->video_tracks.at(0).infinite_length && m->audio_tracks.size() == 0) { - g.out = g.in + 100; - } else { - long length = m->get_length_in_frames(seq->frame_rate); - g.out = entry_point + length - default_clip_in; - if (m->using_inout) { - g.out -= (length - default_clip_out); - } - } + switch (medium->get_type()) { + case MEDIA_TYPE_FOOTAGE: + // is video source a still image? + if (m->video_tracks.size() > 0 && m->video_tracks.at(0).infinite_length && m->audio_tracks.size() == 0) { + g.out = g.in + 100; + } else { + long length = m->get_length_in_frames(seq->frame_rate); + g.out = entry_point + length - default_clip_in; + if (m->using_inout) { + g.out -= (length - default_clip_out); + } + } - for (int j=0;jaudio_tracks.size();j++) { - if (m->audio_tracks.at(j).enabled) { - g.track = j; - g.media_stream = m->audio_tracks.at(j).file_index; - ghosts.append(g); - audio_ghosts = true; - } - } - for (int j=0;jvideo_tracks.size();j++) { - if (m->video_tracks.at(j).enabled) { - g.track = -1-j; - g.media_stream = m->video_tracks.at(j).file_index; - ghosts.append(g); - video_ghosts = true; - } - } - break; - case MEDIA_TYPE_SEQUENCE: - g.out = entry_point + sequence_length - default_clip_in; + for (int j=0;jaudio_tracks.size();j++) { + if (m->audio_tracks.at(j).enabled) { + g.track = j; + g.media_stream = m->audio_tracks.at(j).file_index; + ghosts.append(g); + audio_ghosts = true; + } + } + for (int j=0;jvideo_tracks.size();j++) { + if (m->video_tracks.at(j).enabled) { + g.track = -1-j; + g.media_stream = m->video_tracks.at(j).file_index; + ghosts.append(g); + video_ghosts = true; + } + } + break; + case MEDIA_TYPE_SEQUENCE: + g.out = entry_point + sequence_length - default_clip_in; - if (s->using_workarea) { - g.out -= (sequence_length - default_clip_out); - } + if (s->using_workarea) { + g.out -= (sequence_length - default_clip_out); + } - g.track = -1; - ghosts.append(g); - g.track = 0; - ghosts.append(g); + g.track = -1; + ghosts.append(g); + g.track = 0; + ghosts.append(g); - video_ghosts = true; - audio_ghosts = true; - break; - } - entry_point = g.out; - } - } - for (int i=0;i added_clips; - for (int i=0;i added_clips; + for (int i=0;imedia = g.media; - c->media_stream = g.media_stream; - c->timeline_in = g.in; - c->timeline_out = g.out; - c->clip_in = g.clip_in; - c->track = g.track; - if (c->media->get_type() == MEDIA_TYPE_FOOTAGE) { - FootagePtr m = c->media->to_footage(); - if (m->video_tracks.size() == 0) { - // audio only (greenish) - c->color_r = 128; - c->color_g = 192; - c->color_b = 128; - } else if (m->audio_tracks.size() == 0) { - // video only (orangeish) - c->color_r = 192; - c->color_g = 160; - c->color_b = 128; - } else { - // video and audio (blueish) - c->color_r = 128; - c->color_g = 128; - c->color_b = 192; - } - c->name = m->name; - } else if (c->media->get_type() == MEDIA_TYPE_SEQUENCE) { - // sequence (red?ish?) - c->color_r = 192; - c->color_g = 128; - c->color_b = 128; + ClipPtr c = ClipPtr(new Clip(s)); + c->media = g.media; + c->media_stream = g.media_stream; + c->timeline_in = g.in; + c->timeline_out = g.out; + c->clip_in = g.clip_in; + c->track = g.track; + if (c->media->get_type() == MEDIA_TYPE_FOOTAGE) { + FootagePtr m = c->media->to_footage(); + if (m->video_tracks.size() == 0) { + // audio only (greenish) + c->color_r = 128; + c->color_g = 192; + c->color_b = 128; + } else if (m->audio_tracks.size() == 0) { + // video only (orangeish) + c->color_r = 192; + c->color_g = 160; + c->color_b = 128; + } else { + // video and audio (blueish) + c->color_r = 128; + c->color_g = 128; + c->color_b = 192; + } + c->name = m->name; + } else if (c->media->get_type() == MEDIA_TYPE_SEQUENCE) { + // sequence (red?ish?) + c->color_r = 192; + c->color_g = 128; + c->color_b = 128; - SequencePtr media = c->media->to_sequence(); - c->name = media->name; - } - c->recalculateMaxLength(); - added_clips.append(c); - } - ca->append(new AddClipCommand(s, added_clips)); + SequencePtr media = c->media->to_sequence(); + c->name = media->name; + } + c->recalculateMaxLength(); + added_clips.append(c); + } + ca->append(new AddClipCommand(s, added_clips)); - // link clips from the same media - for (int i=0;imedia == cc->media) { - c->linked.append(j); - } - } + // link clips from the same media + for (int i=0;imedia == cc->media) { + c->linked.append(j); + } + } - if (olive::CurrentConfig.add_default_effects_to_clips) { - if (c->track < 0) { - // add default video effects - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TRANSFORM, EFFECT_TYPE_EFFECT))); - } else { - // add default audio effects - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_VOLUME, EFFECT_TYPE_EFFECT))); - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_PAN, EFFECT_TYPE_EFFECT))); - } - } - } - if (olive::CurrentConfig.enable_seek_to_import) { - panel_sequence_viewer->seek(earliest_point); - } - ghosts.clear(); - importing = false; - snapped = false; + if (olive::CurrentConfig.add_default_effects_to_clips) { + if (c->track < 0) { + // add default video effects + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TRANSFORM, EFFECT_TYPE_EFFECT))); + } else { + // add default audio effects + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_VOLUME, EFFECT_TYPE_EFFECT))); + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_PAN, EFFECT_TYPE_EFFECT))); + } + } + } + if (olive::CurrentConfig.enable_seek_to_import) { + panel_sequence_viewer->seek(earliest_point); + } + ghosts.clear(); + importing = false; + snapped = false; } int Timeline::get_track_height_size(bool video) { - if (video) { - return video_track_heights.size(); - } else { - return audio_track_heights.size(); - } + if (video) { + return video_track_heights.size(); + } else { + return audio_track_heights.size(); + } } void Timeline::add_transition() { - ComboAction* ca = new ComboAction(); - bool adding = false; + ComboAction* ca = new ComboAction(); + bool adding = false; - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr && is_clip_selected(c, true)) { - int transition_to_add = (c->track < 0) ? TRANSITION_INTERNAL_CROSSDISSOLVE : TRANSITION_INTERNAL_LINEARFADE; - if (c->get_opening_transition() == nullptr) { - ca->append(new AddTransitionCommand(c, nullptr, nullptr, get_internal_meta(transition_to_add, EFFECT_TYPE_TRANSITION), kTransitionOpening, 30)); - adding = true; - } - if (c->get_closing_transition() == nullptr) { - ca->append(new AddTransitionCommand(c, nullptr, nullptr, get_internal_meta(transition_to_add, EFFECT_TYPE_TRANSITION), kTransitionClosing, 30)); - adding = true; - } - } - } + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr && is_clip_selected(c, true)) { + int transition_to_add = (c->track < 0) ? TRANSITION_INTERNAL_CROSSDISSOLVE : TRANSITION_INTERNAL_LINEARFADE; + if (c->get_opening_transition() == nullptr) { + ca->append(new AddTransitionCommand(c, nullptr, nullptr, get_internal_meta(transition_to_add, EFFECT_TYPE_TRANSITION), kTransitionOpening, 30)); + adding = true; + } + if (c->get_closing_transition() == nullptr) { + ca->append(new AddTransitionCommand(c, nullptr, nullptr, get_internal_meta(transition_to_add, EFFECT_TYPE_TRANSITION), kTransitionClosing, 30)); + adding = true; + } + } + } - if (adding) { - olive::UndoStack.push(ca); - } else { - delete ca; - } + if (adding) { + olive::UndoStack.push(ca); + } else { + delete ca; + } - update_ui(true); + update_ui(true); } void Timeline::nest() { - if (olive::ActiveSequence != nullptr) { - QVector selected_clips; - long earliest_point = LONG_MAX; + if (olive::ActiveSequence != nullptr) { + QVector selected_clips; + long earliest_point = LONG_MAX; - // get selected clips - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr && is_clip_selected(c, true)) { - selected_clips.append(i); - earliest_point = qMin(c->timeline_in, earliest_point); - } - } - - // nest them - if (!selected_clips.isEmpty()) { - ComboAction* ca = new ComboAction(); - - SequencePtr s(new Sequence()); - - // create "nest" sequence - s->name = panel_project->get_next_sequence_name(tr("Nested Sequence")); - s->width = olive::ActiveSequence->width; - s->height = olive::ActiveSequence->height; - s->frame_rate = olive::ActiveSequence->frame_rate; - s->audio_frequency = olive::ActiveSequence->audio_frequency; - s->audio_layout = olive::ActiveSequence->audio_layout; - - // copy all selected clips to the nest - for (int i=0;iappend(new DeleteClipAction(olive::ActiveSequence, selected_clips.at(i))); - - // copy to new - ClipPtr copy(olive::ActiveSequence->clips.at(selected_clips.at(i))->copy(s)); - copy->timeline_in -= earliest_point; - copy->timeline_out -= earliest_point; - s->clips.append(copy); - } - - // relink clips in new nested sequences - relink_clips_using_ids(selected_clips, s->clips); - - // add sequence to project - Media* m = panel_project->create_sequence_internal(ca, s, false, nullptr); - - // add nested sequence to active sequence - QVector media_list; - media_list.append(m); - create_ghosts_from_media(olive::ActiveSequence, earliest_point, media_list); - add_clips_from_ghosts(ca, olive::ActiveSequence); - - panel_effect_controls->clear_effects(true); - olive::ActiveSequence->selections.clear(); - - olive::UndoStack.push(ca); - - update_ui(true); - } + // get selected clips + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr && is_clip_selected(c, true)) { + selected_clips.append(i); + earliest_point = qMin(c->timeline_in, earliest_point); + } } + + // nest them + if (!selected_clips.isEmpty()) { + ComboAction* ca = new ComboAction(); + + SequencePtr s(new Sequence()); + + // create "nest" sequence + s->name = panel_project->get_next_sequence_name(tr("Nested Sequence")); + s->width = olive::ActiveSequence->width; + s->height = olive::ActiveSequence->height; + s->frame_rate = olive::ActiveSequence->frame_rate; + s->audio_frequency = olive::ActiveSequence->audio_frequency; + s->audio_layout = olive::ActiveSequence->audio_layout; + + // copy all selected clips to the nest + for (int i=0;iappend(new DeleteClipAction(olive::ActiveSequence, selected_clips.at(i))); + + // copy to new + ClipPtr copy(olive::ActiveSequence->clips.at(selected_clips.at(i))->copy(s)); + copy->timeline_in -= earliest_point; + copy->timeline_out -= earliest_point; + s->clips.append(copy); + } + + // relink clips in new nested sequences + relink_clips_using_ids(selected_clips, s->clips); + + // add sequence to project + Media* m = panel_project->create_sequence_internal(ca, s, false, nullptr); + + // add nested sequence to active sequence + QVector media_list; + media_list.append(m); + create_ghosts_from_media(olive::ActiveSequence, earliest_point, media_list); + add_clips_from_ghosts(ca, olive::ActiveSequence); + + panel_effect_controls->clear_effects(true); + olive::ActiveSequence->selections.clear(); + + olive::UndoStack.push(ca); + + update_ui(true); + } + } } 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); + 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); + bool null_sequence = (olive::ActiveSequence == nullptr); - for (int i=0;isetEnabled(!null_sequence); - } - snappingButton->setEnabled(!null_sequence); - zoomInButton->setEnabled(!null_sequence); - zoomOutButton->setEnabled(!null_sequence); - recordButton->setEnabled(!null_sequence); - addButton->setEnabled(!null_sequence); - headers->setEnabled(!null_sequence); + for (int i=0;isetEnabled(!null_sequence); + } + snappingButton->setEnabled(!null_sequence); + zoomInButton->setEnabled(!null_sequence); + zoomOutButton->setEnabled(!null_sequence); + recordButton->setEnabled(!null_sequence); + addButton->setEnabled(!null_sequence); + headers->setEnabled(!null_sequence); - QString title = tr("Timeline: "); - if (null_sequence) { - setWindowTitle(title + tr("")); - } else { - setWindowTitle(title + olive::ActiveSequence->name); - update_ui(false); - } + UpdateTitle(); } int Timeline::get_snap_range() { - return getFrameFromScreenPoint(zoom, 10); + return getFrameFromScreenPoint(zoom, 10); } bool Timeline::focused() { - return (olive::ActiveSequence != nullptr && (headers->hasFocus() || video_area->hasFocus() || audio_area->hasFocus())); + return (olive::ActiveSequence != nullptr && (headers->hasFocus() || video_area->hasFocus() || audio_area->hasFocus())); } void Timeline::repaint_timeline() { - if (!block_repaints) { - bool draw = true; + if (!block_repaints) { + bool draw = true; - if (olive::ActiveSequence != nullptr - && !horizontalScrollBar->isSliderDown() - && !horizontalScrollBar->is_resizing() - && panel_sequence_viewer->playing - && !zoom_just_changed) { - // auto scroll - if (olive::CurrentConfig.autoscroll == AUTOSCROLL_PAGE_SCROLL) { - int playhead_x = getTimelineScreenPointFromFrame(olive::ActiveSequence->playhead); - if (playhead_x < 0 || playhead_x > (editAreas->width() - videoScrollbar->width())) { - horizontalScrollBar->setValue(getScreenPointFromFrame(zoom, olive::ActiveSequence->playhead)); - draw = false; - } - } else if (olive::CurrentConfig.autoscroll == AUTOSCROLL_SMOOTH_SCROLL) { - if (center_scroll_to_playhead(horizontalScrollBar, zoom, olive::ActiveSequence->playhead)) { - draw = false; - } - } - } + if (olive::ActiveSequence != nullptr + && !horizontalScrollBar->isSliderDown() + && !horizontalScrollBar->is_resizing() + && panel_sequence_viewer->playing + && !zoom_just_changed) { + // auto scroll + if (olive::CurrentConfig.autoscroll == AUTOSCROLL_PAGE_SCROLL) { + int playhead_x = getTimelineScreenPointFromFrame(olive::ActiveSequence->playhead); + if (playhead_x < 0 || playhead_x > (editAreas->width() - videoScrollbar->width())) { + horizontalScrollBar->setValue(getScreenPointFromFrame(zoom, olive::ActiveSequence->playhead)); + draw = false; + } + } else if (olive::CurrentConfig.autoscroll == AUTOSCROLL_SMOOTH_SCROLL) { + if (center_scroll_to_playhead(horizontalScrollBar, zoom, olive::ActiveSequence->playhead)) { + draw = false; + } + } + } - if (draw) { - headers->update(); - video_area->update(); - audio_area->update(); + if (draw) { + headers->update(); + video_area->update(); + audio_area->update(); - if (olive::ActiveSequence != nullptr - && !zoom_just_changed) { - set_sb_max(); - } - } + if (olive::ActiveSequence != nullptr + && !zoom_just_changed) { + set_sb_max(); + } + } - zoom_just_changed = false; - } + zoom_just_changed = false; + } } void Timeline::select_all() { - if (olive::ActiveSequence != nullptr) { - olive::ActiveSequence->selections.clear(); - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr) { - Selection s; - s.in = c->timeline_in; - s.out = c->timeline_out; - s.track = c->track; - olive::ActiveSequence->selections.append(s); - } - } - repaint_timeline(); - } + if (olive::ActiveSequence != nullptr) { + olive::ActiveSequence->selections.clear(); + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr) { + Selection s; + s.in = c->timeline_in; + s.out = c->timeline_out; + s.track = c->track; + olive::ActiveSequence->selections.append(s); + } + } + repaint_timeline(); + } } void Timeline::scroll_to_frame(long frame) { - scroll_to_frame_internal(horizontalScrollBar, frame, zoom, timeline_area->width()); + scroll_to_frame_internal(horizontalScrollBar, frame, zoom, timeline_area->width()); } void Timeline::select_from_playhead() { - olive::ActiveSequence->selections.clear(); - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr - && c->timeline_in <= olive::ActiveSequence->playhead - && c->timeline_out > olive::ActiveSequence->playhead) { - Selection s; - s.in = c->timeline_in; - s.out = c->timeline_out; - s.track = c->track; - olive::ActiveSequence->selections.append(s); - } - } + olive::ActiveSequence->selections.clear(); + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr + && c->timeline_in <= olive::ActiveSequence->playhead + && c->timeline_out > olive::ActiveSequence->playhead) { + Selection s; + s.in = c->timeline_in; + s.out = c->timeline_out; + s.track = c->track; + olive::ActiveSequence->selections.append(s); + } + } } bool Timeline::can_ripple_empty_space(long frame, int track) { - bool can_ripple_delete = true; - bool at_end_of_sequence = true; - rc_ripple_min = 0; - rc_ripple_max = LONG_MAX; + bool can_ripple_delete = true; + bool at_end_of_sequence = true; + rc_ripple_min = 0; + rc_ripple_max = LONG_MAX; - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr) { - if (c->timeline_in > frame || c->timeline_out > frame) { - at_end_of_sequence = false; - } - if (c->track == track) { - if (c->timeline_in <= frame && c->timeline_out >= frame) { - can_ripple_delete = false; - break; - } else if (c->timeline_out < frame) { - rc_ripple_min = qMax(rc_ripple_min, c->timeline_out); - } else if (c->timeline_in > frame) { - rc_ripple_max = qMin(rc_ripple_max, c->timeline_in); - } - } - } - } + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr) { + if (c->timeline_in > frame || c->timeline_out > frame) { + at_end_of_sequence = false; + } + if (c->track == track) { + if (c->timeline_in <= frame && c->timeline_out >= frame) { + can_ripple_delete = false; + break; + } else if (c->timeline_out < frame) { + rc_ripple_min = qMax(rc_ripple_min, c->timeline_out); + } else if (c->timeline_in > frame) { + rc_ripple_max = qMin(rc_ripple_max, c->timeline_in); + } + } + } + } - return (can_ripple_delete && !at_end_of_sequence); + return (can_ripple_delete && !at_end_of_sequence); } void Timeline::ripple_delete_empty_space() { - QVector sels; + QVector sels; - Selection s; - s.in = rc_ripple_min; - s.out = rc_ripple_max; - s.track = cursor_track; + Selection s; + s.in = rc_ripple_min; + s.out = rc_ripple_max; + s.track = cursor_track; - sels.append(s); + sels.append(s); - delete_selection(sels, true); + delete_selection(sels, true); } void Timeline::resizeEvent(QResizeEvent *) { - // adjust maximum scrollbar - if (olive::ActiveSequence != nullptr) set_sb_max(); + // adjust maximum scrollbar + if (olive::ActiveSequence != nullptr) set_sb_max(); - // resize tool button widget to its contents - QList tool_button_children = tool_button_widget->findChildren(); + // resize tool button widget to its contents + QList tool_button_children = tool_button_widget->findChildren(); - int horizontal_spacing = static_cast(tool_button_widget->layout())->horizontalSpacing(); - int vertical_spacing = static_cast(tool_button_widget->layout())->verticalSpacing(); - int total_area = tool_button_widget->height(); + int horizontal_spacing = static_cast(tool_button_widget->layout())->horizontalSpacing(); + int vertical_spacing = static_cast(tool_button_widget->layout())->verticalSpacing(); + int total_area = tool_button_widget->height(); - int button_count = tool_button_children.size(); - int button_height = tool_button_children.at(0)->sizeHint().height() + vertical_spacing; + int button_count = tool_button_children.size(); + int button_height = tool_button_children.at(0)->sizeHint().height() + vertical_spacing; - int cols = 0; + int cols = 0; - int col_height; + int col_height; - if (button_height < total_area) { - do { - cols++; - col_height = (qCeil(double(button_count)/double(cols))*button_height)-vertical_spacing; - } while (col_height > total_area); - } else { - cols = button_count; - } + if (button_height < total_area) { + do { + cols++; + col_height = (qCeil(double(button_count)/double(cols))*button_height)-vertical_spacing; + } while (col_height > total_area); + } else { + cols = button_count; + } - tool_button_widget->setFixedWidth((tool_button_children.at(0)->sizeHint().width())*cols + horizontal_spacing*(cols-1) + 1); + tool_button_widget->setFixedWidth((tool_button_children.at(0)->sizeHint().width())*cols + horizontal_spacing*(cols-1) + 1); } void Timeline::delete_in_out_internal(bool ripple) { - if (olive::ActiveSequence != nullptr && olive::ActiveSequence->using_workarea) { - QVector areas; - int video_tracks = 0, audio_tracks = 0; - olive::ActiveSequence->getTrackLimits(&video_tracks, &audio_tracks); - for (int i=video_tracks;i<=audio_tracks;i++) { - Selection s; - s.in = olive::ActiveSequence->workarea_in; - s.out = olive::ActiveSequence->workarea_out; - s.track = i; - areas.append(s); - } - ComboAction* ca = new ComboAction(); - delete_areas_and_relink(ca, areas, true); - if (ripple) ripple_clips(ca, olive::ActiveSequence, olive::ActiveSequence->workarea_in, olive::ActiveSequence->workarea_in - olive::ActiveSequence->workarea_out); - ca->append(new SetTimelineInOutCommand(olive::ActiveSequence, false, 0, 0)); - olive::UndoStack.push(ca); - update_ui(true); + if (olive::ActiveSequence != nullptr && olive::ActiveSequence->using_workarea) { + QVector areas; + int video_tracks = 0, audio_tracks = 0; + olive::ActiveSequence->getTrackLimits(&video_tracks, &audio_tracks); + for (int i=video_tracks;i<=audio_tracks;i++) { + Selection s; + s.in = olive::ActiveSequence->workarea_in; + s.out = olive::ActiveSequence->workarea_out; + s.track = i; + areas.append(s); } + ComboAction* ca = new ComboAction(); + delete_areas_and_relink(ca, areas, true); + if (ripple) ripple_clips(ca, olive::ActiveSequence, olive::ActiveSequence->workarea_in, olive::ActiveSequence->workarea_in - olive::ActiveSequence->workarea_out); + ca->append(new SetTimelineInOutCommand(olive::ActiveSequence, false, 0, 0)); + olive::UndoStack.push(ca); + update_ui(true); + } } void Timeline::toggle_enable_on_selected_clips() { - if (olive::ActiveSequence != nullptr) { - ComboAction* ca = new ComboAction(); - bool push_undo = false; - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr && is_clip_selected(c, true)) { - ca->append(new SetBool(&c->enabled, !c->enabled)); - push_undo = true; - } - } - if (push_undo) { - olive::UndoStack.push(ca); - update_ui(true); - } else { - delete ca; - } + if (olive::ActiveSequence != nullptr) { + ComboAction* ca = new ComboAction(); + bool push_undo = false; + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr && is_clip_selected(c, true)) { + ca->append(new SetBool(&c->enabled, !c->enabled)); + push_undo = true; + } } + if (push_undo) { + olive::UndoStack.push(ca); + update_ui(true); + } else { + delete ca; + } + } } void Timeline::delete_selection(QVector& selections, bool ripple_delete) { - if (selections.size() > 0) { - panel_effect_controls->clear_effects(true); + if (selections.size() > 0) { + panel_effect_controls->clear_effects(true); - ComboAction* ca = new ComboAction(); + ComboAction* ca = new ComboAction(); - delete_areas_and_relink(ca, selections, true); + delete_areas_and_relink(ca, selections, true); - if (ripple_delete) { - long ripple_point = selections.at(0).in; - long ripple_length = selections.at(0).out - selections.at(0).in; + if (ripple_delete) { + long ripple_point = selections.at(0).in; + long ripple_length = selections.at(0).out - selections.at(0).in; - // retrieve ripple_point and ripple_length from current selection - for (int i=1;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr && c->timeline_in < ripple_point && c->timeline_out > ripple_point) { - // conflict detected, but this clip may be getting deleted so let's check - bool deleted = false; - for (int j=0;jtrack - && !(c->timeline_in < s.in && c->timeline_out < s.in) - && !(c->timeline_in > s.out && c->timeline_out > s.out)) { - deleted = true; - break; - } - } - if (!deleted) { - for (int j=0;jclips.size();j++) { - ClipPtr cc = olive::ActiveSequence->clips.at(j); - if (cc != nullptr - && cc->track == c->track - && cc->timeline_in > c->timeline_out - && cc->timeline_in < c->timeline_out + ripple_length) { - ripple_length = cc->timeline_in - c->timeline_out; - } - } - } - } - } + bool can_ripple = true; + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr && c->timeline_in < ripple_point && c->timeline_out > ripple_point) { + // conflict detected, but this clip may be getting deleted so let's check + bool deleted = false; + for (int j=0;jtrack + && !(c->timeline_in < s.in && c->timeline_out < s.in) + && !(c->timeline_in > s.out && c->timeline_out > s.out)) { + deleted = true; + break; + } + } + if (!deleted) { + for (int j=0;jclips.size();j++) { + ClipPtr cc = olive::ActiveSequence->clips.at(j); + if (cc != nullptr + && cc->track == c->track + && cc->timeline_in > c->timeline_out + && cc->timeline_in < c->timeline_out + ripple_length) { + ripple_length = cc->timeline_in - c->timeline_out; + } + } + } + } + } - if (can_ripple) { - ripple_clips(ca, olive::ActiveSequence, ripple_point, -ripple_length); - panel_sequence_viewer->seek(ripple_point-1); - } - } + if (can_ripple) { + ripple_clips(ca, olive::ActiveSequence, ripple_point, -ripple_length); + panel_sequence_viewer->seek(ripple_point-1); + } + } - olive::UndoStack.push(ca); + olive::UndoStack.push(ca); - update_ui(true); - } + update_ui(true); + } } void Timeline::set_zoom_value(double v) { - // set zoom value - zoom = v; + // set zoom value + zoom = v; - // update header zoom to match - headers->update_zoom(zoom); + // update header zoom to match + headers->update_zoom(zoom); - // set flag that zoom has just changed to prevent auto-scrolling since we change the scroll below - zoom_just_changed = true; + // set flag that zoom has just changed to prevent auto-scrolling since we change the scroll below + zoom_just_changed = true; - // set scrollbar to center the playhead - if (olive::ActiveSequence != nullptr - && !horizontalScrollBar->is_resizing()) { - // update scrollbar maximum value for new zoom - set_sb_max(); + // set scrollbar to center the playhead + if (olive::ActiveSequence != nullptr + && !horizontalScrollBar->is_resizing()) { + // update scrollbar maximum value for new zoom + set_sb_max(); - center_scroll_to_playhead(horizontalScrollBar, zoom, olive::ActiveSequence->playhead); - } + center_scroll_to_playhead(horizontalScrollBar, zoom, olive::ActiveSequence->playhead); + } - // repaint the timeline for the new zoom/location - repaint_timeline(); + // repaint the timeline for the new zoom/location + repaint_timeline(); } void Timeline::multiply_zoom(double m) { - showing_all = false; - set_zoom_value(zoom * m); + showing_all = false; + set_zoom_value(zoom * m); } void Timeline::decheck_tool_buttons(QObject* sender) { - for (int i=0;isetChecked(tool_buttons.at(i) == sender); - } + for (int i=0;isetChecked(tool_buttons.at(i) == 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; + 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); + multiply_zoom(2.0); } void Timeline::zoom_out() { - multiply_zoom(0.5); + multiply_zoom(0.5); } bool is_clip_selected(ClipPtr clip, bool containing) { - for (int i=0;isequence->selections.size();i++) { - const Selection& s = clip->sequence->selections.at(i); - if (clip->track == s.track && ((clip->timeline_in >= s.in && clip->timeline_out <= s.out && containing) || - (!containing && !(clip->timeline_in < s.in && clip->timeline_out < s.in) && !(clip->timeline_in > s.in && clip->timeline_out > s.in)))) { - return true; - } - } - return false; + for (int i=0;isequence->selections.size();i++) { + const Selection& s = clip->sequence->selections.at(i); + if (clip->track == s.track && ((clip->timeline_in >= s.in && clip->timeline_out <= s.out && containing) || + (!containing && !(clip->timeline_in < s.in && clip->timeline_out < s.in) && !(clip->timeline_in > s.in && clip->timeline_out > s.in)))) { + return true; + } + } + return false; } void Timeline::snapping_clicked(bool checked) { - snapping = checked; + snapping = checked; } ClipPtr Timeline::split_clip(ComboAction* ca, bool transitions, int p, long frame) { - return split_clip(ca, transitions, p, frame, frame); + return split_clip(ca, transitions, p, frame, frame); } ClipPtr Timeline::split_clip(ComboAction* ca, bool transitions, int p, long frame, long post_in) { - ClipPtr pre = olive::ActiveSequence->clips.at(p); - if (pre != nullptr && pre->timeline_in < frame && pre->timeline_out > frame) { // guard against attempts to split at in/out points - bool splitting_closing_dual_transition = false; + ClipPtr pre = olive::ActiveSequence->clips.at(p); + if (pre != nullptr && pre->timeline_in < frame && pre->timeline_out > frame) { // guard against attempts to split at in/out points + bool splitting_closing_dual_transition = false; - if (transitions - && pre->get_closing_transition() != nullptr - && pre->get_closing_transition()->secondary_clip != nullptr) { - splitting_closing_dual_transition = true; - } + if (transitions + && pre->get_closing_transition() != nullptr + && pre->get_closing_transition()->secondary_clip != nullptr) { + splitting_closing_dual_transition = true; + } - ClipPtr post = ClipPtr(pre->copy(olive::ActiveSequence, transitions && !splitting_closing_dual_transition)); + ClipPtr post = ClipPtr(pre->copy(olive::ActiveSequence, transitions && !splitting_closing_dual_transition)); - long new_clip_length = frame - pre->timeline_in; + long new_clip_length = frame - pre->timeline_in; - post->timeline_in = post_in; - post->clip_in = pre->clip_in + (post->timeline_in - pre->timeline_in); + post->timeline_in = post_in; + post->clip_in = pre->clip_in + (post->timeline_in - pre->timeline_in); - move_clip(ca, pre, pre->timeline_in, frame, pre->clip_in, pre->track); + move_clip(ca, pre, pre->timeline_in, frame, pre->clip_in, pre->track); - if (pre->get_opening_transition() != nullptr) { -// if (frame < pre->timeline_in + pre->get_opening_transition()->length && pre->get_opening_transition()->secondary_clip != nullptr) { - // separate shared transition -// ca->append(new SetPointer((void**) &pre->get_opening_transition()->secondary_clip, nullptr)); -// pre->get_opening_transition()->secondary_clip->closing_transition = pre->get_opening_transition()->copy(pre->get_opening_transition()->secondary_clip, nullptr); -// } + if (pre->get_opening_transition() != nullptr) { + // if (frame < pre->timeline_in + pre->get_opening_transition()->length && pre->get_opening_transition()->secondary_clip != nullptr) { + // separate shared transition + // ca->append(new SetPointer((void**) &pre->get_opening_transition()->secondary_clip, nullptr)); + // pre->get_opening_transition()->secondary_clip->closing_transition = pre->get_opening_transition()->copy(pre->get_opening_transition()->secondary_clip, nullptr); + // } - if (pre->get_opening_transition()->get_true_length() > new_clip_length) { + if (pre->get_opening_transition()->get_true_length() > new_clip_length) { ca->append(new ModifyTransitionCommand(pre->get_opening_transition(), new_clip_length)); } - } - if (pre->get_closing_transition() != nullptr) { - if (splitting_closing_dual_transition) { - // just move closing transition to post clip + } + if (pre->get_closing_transition() != nullptr) { + if (splitting_closing_dual_transition) { + // just move closing transition to post clip - // WORKAROUND + // WORKAROUND ca->append(new DeleteTransitionCommand(pre->closing_transition)); - } else { + } else { ca->append(new DeleteTransitionCommand(pre->closing_transition)); - if (post->get_closing_transition() != nullptr) { - if (pre->get_closing_transition()->secondary_clip == nullptr) { - post->get_closing_transition()->set_length(qMin(long(post->get_closing_transition()->get_true_length()), post->getLength())); - } + if (post->get_closing_transition() != nullptr) { + if (pre->get_closing_transition()->secondary_clip == nullptr) { + post->get_closing_transition()->set_length(qMin(long(post->get_closing_transition()->get_true_length()), post->getLength())); + } - if (post->get_closing_transition()->get_length() > post->getLength()) { - post->get_closing_transition()->set_length(post->getLength()); - } - } - } - } + if (post->get_closing_transition()->get_length() > post->getLength()) { + post->get_closing_transition()->set_length(post->getLength()); + } + } + } + } - return post; - } - return nullptr; + return post; + } + return nullptr; } bool Timeline::has_clip_been_split(int c) { - for (int i=0;iclips.at(clip); - if (c != nullptr) { - QVector pre_clips; - QVector post_clips; + ClipPtr c = olive::ActiveSequence->clips.at(clip); + if (c != nullptr) { + QVector pre_clips; + QVector post_clips; - ClipPtr post = split_clip(ca, true, clip, frame); + ClipPtr post = split_clip(ca, true, clip, frame); - // if alt is not down, split clips links too - if (post == nullptr) { - return false; - } else { - post_clips.append(post); - if (relink) { - pre_clips.append(clip); + // if alt is not down, split clips links too + if (post == nullptr) { + return false; + } else { + post_clips.append(post); + if (relink) { + pre_clips.append(clip); - bool original_clip_is_selected = is_clip_selected(c, true); + bool original_clip_is_selected = is_clip_selected(c, true); - // find linked clips of old clip - for (int i=0;ilinked.size();i++) { - int l = c->linked.at(i); - if (!has_clip_been_split(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); - ClipPtr s = split_clip(ca, true, l, frame); - if (s != nullptr) { - pre_clips.append(l); - post_clips.append(s); - } - } - } - } + // find linked clips of old clip + for (int i=0;ilinked.size();i++) { + int l = c->linked.at(i); + if (!has_clip_been_split(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); + ClipPtr s = split_clip(ca, true, l, frame); + if (s != nullptr) { + pre_clips.append(l); + post_clips.append(s); + } + } + } + } - relink_clips_using_ids(pre_clips, post_clips); - } - ca->append(new AddClipCommand(olive::ActiveSequence, post_clips)); - return true; - } - } - return false; + relink_clips_using_ids(pre_clips, post_clips); + } + ca->append(new AddClipCommand(olive::ActiveSequence, post_clips)); + return true; + } + } + return false; } void Timeline::clean_up_selections(QVector& areas) { - for (int i=0;i ss.out) { - // do nothing - } else if (s.in >= ss.in && s.out <= ss.out) { - remove = true; - } else if (s.in <= ss.out && s.out > ss.out) { - ss.out = s.out; - remove = true; - } else if (s.out >= ss.in && s.in < ss.in) { - ss.in = s.in; - remove = true; - } - if (remove) { - areas.removeAt(i); - i--; - break; - } - } - } - } - } + for (int i=0;i ss.out) { + // do nothing + } else if (s.in >= ss.in && s.out <= ss.out) { + remove = true; + } else if (s.in <= ss.out && s.out > ss.out) { + ss.out = s.out; + remove = true; + } else if (s.out >= ss.in && s.in < ss.in) { + ss.in = s.in; + remove = true; + } + if (remove) { + areas.removeAt(i); + i--; + break; + } + } + } + } + } } bool selection_contains_transition(const Selection& s, ClipPtr c, int type) { if (type == kTransitionOpening) { - return c->get_opening_transition() != nullptr - && s.out == c->timeline_in + c->get_opening_transition()->get_true_length() - && ((c->get_opening_transition()->secondary_clip == nullptr && s.in == c->timeline_in) - || (c->get_opening_transition()->secondary_clip != nullptr && s.in == c->timeline_in - c->get_opening_transition()->get_true_length())); - } else { - return c->get_closing_transition() != nullptr - && s.in == c->timeline_out - c->get_closing_transition()->get_true_length() - && ((c->get_closing_transition()->secondary_clip == nullptr && s.out == c->timeline_out) - || (c->get_closing_transition()->secondary_clip != nullptr && s.out == c->timeline_out + c->get_closing_transition()->get_true_length())); - } + return c->get_opening_transition() != nullptr + && s.out == c->timeline_in + c->get_opening_transition()->get_true_length() + && ((c->get_opening_transition()->secondary_clip == nullptr && s.in == c->timeline_in) + || (c->get_opening_transition()->secondary_clip != nullptr && s.in == c->timeline_in - c->get_opening_transition()->get_true_length())); + } else { + return c->get_closing_transition() != nullptr + && s.in == c->timeline_out - c->get_closing_transition()->get_true_length() + && ((c->get_closing_transition()->secondary_clip == nullptr && s.out == c->timeline_out) + || (c->get_closing_transition()->secondary_clip != nullptr && s.out == c->timeline_out + c->get_closing_transition()->get_true_length())); + } } void Timeline::delete_areas_and_relink(ComboAction* ca, QVector& areas, bool deselect_areas) { - clean_up_selections(areas); - panel_effect_controls->clear_effects(true); + clean_up_selections(areas); + panel_effect_controls->clear_effects(true); - QVector pre_clips; - QVector post_clips; + QVector pre_clips; + QVector post_clips; - for (int i=0;iclips.size();j++) { - ClipPtr c = olive::ActiveSequence->clips.at(j); - if (c != nullptr && c->track == s.track && !c->undeletable) { + for (int i=0;iclips.size();j++) { + ClipPtr c = olive::ActiveSequence->clips.at(j); + if (c != nullptr && c->track == s.track && !c->undeletable) { if (selection_contains_transition(s, c, kTransitionOpening)) { - // delete opening transition + // delete opening transition ca->append(new DeleteTransitionCommand(c->opening_transition)); } else if (selection_contains_transition(s, c, kTransitionClosing)) { - // delete closing transition + // delete closing transition ca->append(new DeleteTransitionCommand(c->closing_transition)); - } else if (c->timeline_in >= s.in && c->timeline_out <= s.out) { - // clips falls entirely within deletion area - ca->append(new DeleteClipAction(olive::ActiveSequence, j)); - } else if (c->timeline_in < s.in && c->timeline_out > s.out) { - // middle of clip is within deletion area + } else if (c->timeline_in >= s.in && c->timeline_out <= s.out) { + // clips falls entirely within deletion area + ca->append(new DeleteClipAction(olive::ActiveSequence, j)); + } else if (c->timeline_in < s.in && c->timeline_out > s.out) { + // middle of clip is within deletion area - // duplicate clip - ClipPtr post = split_clip(ca, true, j, s.in, s.out); + // duplicate clip + ClipPtr post = split_clip(ca, true, j, s.in, s.out); - pre_clips.append(j); - post_clips.append(post); - } else if (c->timeline_in < s.in && c->timeline_out > s.in) { - // only out point is in deletion area - move_clip(ca, c, c->timeline_in, s.in, c->clip_in, c->track); + pre_clips.append(j); + post_clips.append(post); + } else if (c->timeline_in < s.in && c->timeline_out > s.in) { + // only out point is in deletion area + move_clip(ca, c, c->timeline_in, s.in, c->clip_in, c->track); - if (c->get_closing_transition() != nullptr) { - if (s.in < c->timeline_out - c->get_closing_transition()->get_true_length()) { + if (c->get_closing_transition() != nullptr) { + if (s.in < c->timeline_out - c->get_closing_transition()->get_true_length()) { ca->append(new DeleteTransitionCommand(c->closing_transition)); - } else { + } else { ca->append(new ModifyTransitionCommand(c->closing_transition, c->get_closing_transition()->get_true_length() - (c->timeline_out - s.in))); - } - } - } else if (c->timeline_in < s.out && c->timeline_out > s.out) { - // only in point is in deletion area - move_clip(ca, c, s.out, c->timeline_out, c->clip_in + (s.out - c->timeline_in), c->track); + } + } + } else if (c->timeline_in < s.out && c->timeline_out > s.out) { + // only in point is in deletion area + move_clip(ca, c, s.out, c->timeline_out, c->clip_in + (s.out - c->timeline_in), c->track); - if (c->get_opening_transition() != nullptr) { - if (s.out > c->timeline_in + c->get_opening_transition()->get_true_length()) { + if (c->get_opening_transition() != nullptr) { + if (s.out > c->timeline_in + c->get_opening_transition()->get_true_length()) { ca->append(new DeleteTransitionCommand(c->opening_transition)); - } else { + } else { ca->append(new ModifyTransitionCommand(c->opening_transition, c->get_opening_transition()->get_true_length() - (s.out - c->timeline_in))); - } - } - } - } - } - } + } + } + } + } + } + } - // deselect selected clip areas - if (deselect_areas) { - QVector area_copy = areas; - for (int i=0;i area_copy = areas; + for (int i=0;iappend(new AddClipCommand(olive::ActiveSequence, post_clips)); + relink_clips_using_ids(pre_clips, post_clips); + ca->append(new AddClipCommand(olive::ActiveSequence, post_clips)); } void Timeline::copy(bool del) { - bool cleared = false; - bool copied = false; + bool cleared = false; + bool copied = false; - long min_in = 0; + long min_in = 0; - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr) { - for (int j=0;jselections.size();j++) { - const Selection& s = olive::ActiveSequence->selections.at(j); - if (s.track == c->track && !((c->timeline_in <= s.in && c->timeline_out <= s.in) || (c->timeline_in >= s.out && c->timeline_out >= s.out))) { - if (!cleared) { - clear_clipboard(); - cleared = true; - clipboard_type = CLIPBOARD_TYPE_CLIP; - } + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr) { + for (int j=0;jselections.size();j++) { + const Selection& s = olive::ActiveSequence->selections.at(j); + if (s.track == c->track && !((c->timeline_in <= s.in && c->timeline_out <= s.in) || (c->timeline_in >= s.out && c->timeline_out >= s.out))) { + if (!cleared) { + clear_clipboard(); + cleared = true; + clipboard_type = CLIPBOARD_TYPE_CLIP; + } - ClipPtr copied_clip = c->copy(nullptr); + ClipPtr copied_clip = c->copy(nullptr); - // copy linked IDs (we correct these later in paste()) - copied_clip->linked = c->linked; + // copy linked IDs (we correct these later in paste()) + copied_clip->linked = c->linked; - if (copied_clip->timeline_in < s.in) { - copied_clip->clip_in += (s.in - copied_clip->timeline_in); - copied_clip->timeline_in = s.in; - } + if (copied_clip->timeline_in < s.in) { + copied_clip->clip_in += (s.in - copied_clip->timeline_in); + copied_clip->timeline_in = s.in; + } - if (copied_clip->timeline_out > s.out) { - copied_clip->timeline_out = s.out; - } + if (copied_clip->timeline_out > s.out) { + copied_clip->timeline_out = s.out; + } - if (copied) { - min_in = qMin(min_in, s.in); - } else { - min_in = s.in; - copied = true; - } + if (copied) { + min_in = qMin(min_in, s.in); + } else { + min_in = s.in; + copied = true; + } - copied_clip->load_id = i; + copied_clip->load_id = i; - clipboard.append(copied_clip); - } - } - } - } + clipboard.append(copied_clip); + } + } + } + } - for (int i=0;i(clipboard.at(i))->timeline_in -= min_in; - std::static_pointer_cast(clipboard.at(i))->timeline_out -= min_in; - } + for (int i=0;i(clipboard.at(i))->timeline_in -= min_in; + std::static_pointer_cast(clipboard.at(i))->timeline_out -= min_in; + } - if (del && copied) { - delete_selection(olive::ActiveSequence->selections, false); - } + if (del && copied) { + delete_selection(olive::ActiveSequence->selections, false); + } } void Timeline::relink_clips_using_ids(QVector& old_clips, QVector& new_clips) { - // relink pasted clips - for (int i=0;iclips.at(old_clips.at(i)); - for (int j=0;jlinked.size();j++) { - for (int k=0;klinked.at(j) == old_clips.at(k)) { - if (new_clips.at(i) != nullptr) { - new_clips.at(i)->linked.append(k); - } - } - } - } - } + // relink pasted clips + for (int i=0;iclips.at(old_clips.at(i)); + for (int j=0;jlinked.size();j++) { + for (int k=0;klinked.at(j) == old_clips.at(k)) { + if (new_clips.at(i) != nullptr) { + new_clips.at(i)->linked.append(k); + } + } + } + } + } } void Timeline::paste(bool insert) { - if (clipboard.size() > 0) { - if (clipboard_type == CLIPBOARD_TYPE_CLIP) { - ComboAction* ca = new ComboAction(); + if (clipboard.size() > 0) { + if (clipboard_type == CLIPBOARD_TYPE_CLIP) { + ComboAction* ca = new ComboAction(); - // create copies and delete areas that we'll be pasting to - QVector delete_areas; - QVector pasted_clips; - long paste_start = LONG_MAX; - long paste_end = LONG_MIN; - for (int i=0;i(clipboard.at(i)); + // create copies and delete areas that we'll be pasting to + QVector delete_areas; + QVector pasted_clips; + long paste_start = LONG_MAX; + long paste_end = LONG_MIN; + for (int i=0;i(clipboard.at(i)); - // create copy of clip and offset by playhead - ClipPtr cc(c->copy(olive::ActiveSequence)); + // create copy of clip and offset by playhead + ClipPtr cc(c->copy(olive::ActiveSequence)); - // convert frame rates - cc->timeline_in = refactor_frame_number(cc->timeline_in, c->cached_fr, olive::ActiveSequence->frame_rate); - cc->timeline_out = refactor_frame_number(cc->timeline_out, c->cached_fr, olive::ActiveSequence->frame_rate); - cc->clip_in = refactor_frame_number(cc->clip_in, c->cached_fr, olive::ActiveSequence->frame_rate); + // convert frame rates + cc->timeline_in = refactor_frame_number(cc->timeline_in, c->cached_fr, olive::ActiveSequence->frame_rate); + cc->timeline_out = refactor_frame_number(cc->timeline_out, c->cached_fr, olive::ActiveSequence->frame_rate); + cc->clip_in = refactor_frame_number(cc->clip_in, c->cached_fr, olive::ActiveSequence->frame_rate); - cc->timeline_in += olive::ActiveSequence->playhead; - cc->timeline_out += olive::ActiveSequence->playhead; - cc->track = c->track; + cc->timeline_in += olive::ActiveSequence->playhead; + cc->timeline_out += olive::ActiveSequence->playhead; + cc->track = c->track; - paste_start = qMin(paste_start, cc->timeline_in); - paste_end = qMax(paste_end, cc->timeline_out); + paste_start = qMin(paste_start, cc->timeline_in); + paste_end = qMax(paste_end, cc->timeline_out); - pasted_clips.append(cc); + pasted_clips.append(cc); - if (!insert) { - Selection s; - s.in = cc->timeline_in; - s.out = cc->timeline_out; - s.track = c->track; - delete_areas.append(s); - } - } - if (insert) { - split_cache.clear(); - split_all_clips_at_point(ca, olive::ActiveSequence->playhead); - ripple_clips(ca, olive::ActiveSequence, paste_start, paste_end - paste_start); - } else { - delete_areas_and_relink(ca, delete_areas, false); - } + if (!insert) { + Selection s; + s.in = cc->timeline_in; + s.out = cc->timeline_out; + s.track = c->track; + delete_areas.append(s); + } + } + if (insert) { + split_cache.clear(); + split_all_clips_at_point(ca, olive::ActiveSequence->playhead); + ripple_clips(ca, olive::ActiveSequence, paste_start, paste_end - paste_start); + } else { + delete_areas_and_relink(ca, delete_areas, false); + } - // correct linked clips - for (int i=0;i(clipboard.at(i)); + // correct linked clips + for (int i=0;i(clipboard.at(i)); - for (int j=0;jlinked.size();j++) { - for (int k=0;k(clipboard.at(k)); - if (comp->load_id == oc->linked.at(j)) { - pasted_clips.at(i)->linked.append(k); - } - } - } - } + for (int j=0;jlinked.size();j++) { + for (int k=0;k(clipboard.at(k)); + if (comp->load_id == oc->linked.at(j)) { + pasted_clips.at(i)->linked.append(k); + } + } + } + } - ca->append(new AddClipCommand(olive::ActiveSequence, pasted_clips)); + ca->append(new AddClipCommand(olive::ActiveSequence, pasted_clips)); - olive::UndoStack.push(ca); + olive::UndoStack.push(ca); - update_ui(true); + update_ui(true); - if (olive::CurrentConfig.paste_seeks) { - panel_sequence_viewer->seek(paste_end); - } - } else if (clipboard_type == CLIPBOARD_TYPE_EFFECT) { - ComboAction* ca = new ComboAction(); - bool push = false; + if (olive::CurrentConfig.paste_seeks) { + panel_sequence_viewer->seek(paste_end); + } + } else if (clipboard_type == CLIPBOARD_TYPE_EFFECT) { + ComboAction* ca = new ComboAction(); + bool push = false; - bool replace = false; - bool skip = false; - bool ask_conflict = true; + bool replace = false; + bool skip = false; + bool ask_conflict = true; - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr && is_clip_selected(c, true)) { - for (int j=0;j(clipboard.at(j)); - if ((c->track < 0) == (e->meta->subtype == EFFECT_TYPE_VIDEO)) { - int found = -1; - if (ask_conflict) { - replace = false; - skip = false; - } - for (int k=0;keffects.size();k++) { - if (c->effects.at(k)->meta == e->meta) { - found = k; - break; - } - } - if (found >= 0 && ask_conflict) { - QMessageBox box(this); - box.setWindowTitle(tr("Effect already exists")); - box.setText(tr("Clip '%1' already contains a '%2' effect. Would you like to replace it with the pasted one or add it as a separate effect?").arg(c->name, e->meta->name)); - box.setIcon(QMessageBox::Icon::Question); + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr && is_clip_selected(c, true)) { + for (int j=0;j(clipboard.at(j)); + if ((c->track < 0) == (e->meta->subtype == EFFECT_TYPE_VIDEO)) { + int found = -1; + if (ask_conflict) { + replace = false; + skip = false; + } + for (int k=0;keffects.size();k++) { + if (c->effects.at(k)->meta == e->meta) { + found = k; + break; + } + } + if (found >= 0 && ask_conflict) { + QMessageBox box(this); + box.setWindowTitle(tr("Effect already exists")); + box.setText(tr("Clip '%1' already contains a '%2' effect. Would you like to replace it with the pasted one or add it as a separate effect?").arg(c->name, e->meta->name)); + box.setIcon(QMessageBox::Icon::Question); - box.addButton(tr("Add"), QMessageBox::YesRole); - QPushButton* replace_button = box.addButton(tr("Replace"), QMessageBox::NoRole); - QPushButton* skip_button = box.addButton(tr("Skip"), QMessageBox::RejectRole); + box.addButton(tr("Add"), QMessageBox::YesRole); + QPushButton* replace_button = box.addButton(tr("Replace"), QMessageBox::NoRole); + QPushButton* skip_button = box.addButton(tr("Skip"), QMessageBox::RejectRole); - QCheckBox* future_box = new QCheckBox(tr("Do this for all conflicts found"), &box); - box.setCheckBox(future_box); + QCheckBox* future_box = new QCheckBox(tr("Do this for all conflicts found"), &box); + box.setCheckBox(future_box); - box.exec(); + box.exec(); - if (box.clickedButton() == replace_button) { - replace = true; - } else if (box.clickedButton() == skip_button) { - skip = true; - } - ask_conflict = !future_box->isChecked(); - } + if (box.clickedButton() == replace_button) { + replace = true; + } else if (box.clickedButton() == skip_button) { + skip = true; + } + ask_conflict = !future_box->isChecked(); + } - if (found >= 0 && skip) { - // do nothing - } else if (found >= 0 && replace) { - EffectDeleteCommand* delcom = new EffectDeleteCommand(); - delcom->clips.append(c); - delcom->fx.append(found); - ca->append(delcom); + if (found >= 0 && skip) { + // do nothing + } else if (found >= 0 && replace) { + EffectDeleteCommand* delcom = new EffectDeleteCommand(); + delcom->clips.append(c); + delcom->fx.append(found); + ca->append(delcom); - ca->append(new AddEffectCommand(c, e->copy(c), nullptr, found)); - push = true; - } else { - ca->append(new AddEffectCommand(c, e->copy(c), nullptr)); - push = true; - } - } - } - } - } - if (push) { - ca->appendPost(new ReloadEffectsCommand()); - olive::UndoStack.push(ca); - } else { - delete ca; - } - update_ui(true); - } - } + ca->append(new AddEffectCommand(c, e->copy(c), nullptr, found)); + push = true; + } else { + ca->append(new AddEffectCommand(c, e->copy(c), nullptr)); + push = true; + } + } + } + } + } + if (push) { + ca->appendPost(new ReloadEffectsCommand()); + olive::UndoStack.push(ca); + } else { + delete ca; + } + update_ui(true); + } + } } void Timeline::edit_to_point_internal(bool in, bool ripple) { - if (olive::ActiveSequence != nullptr) { - if (olive::ActiveSequence->clips.size() > 0) { - // get track count - int track_min = INT_MAX; - int track_max = INT_MIN; - long sequence_end = 0; + if (olive::ActiveSequence != nullptr) { + if (olive::ActiveSequence->clips.size() > 0) { + // get track count + int track_min = INT_MAX; + int track_max = INT_MIN; + long sequence_end = 0; - bool playhead_falls_on_in = false; - bool playhead_falls_on_out = false; - long next_cut = LONG_MAX; - long prev_cut = 0; + bool playhead_falls_on_in = false; + bool playhead_falls_on_out = false; + long next_cut = LONG_MAX; + long prev_cut = 0; - // find closest in point to playhead - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr) { - track_min = qMin(track_min, c->track); - track_max = qMax(track_max, c->track); + // find closest in point to playhead + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr) { + track_min = qMin(track_min, c->track); + track_max = qMax(track_max, c->track); - sequence_end = qMax(c->timeline_out, sequence_end); + sequence_end = qMax(c->timeline_out, sequence_end); - if (c->timeline_in == olive::ActiveSequence->playhead) - playhead_falls_on_in = true; - if (c->timeline_out == olive::ActiveSequence->playhead) - playhead_falls_on_out = true; - if (c->timeline_in > olive::ActiveSequence->playhead) - next_cut = qMin(c->timeline_in, next_cut); - if (c->timeline_out > olive::ActiveSequence->playhead) - next_cut = qMin(c->timeline_out, next_cut); - if (c->timeline_in < olive::ActiveSequence->playhead) - prev_cut = qMax(c->timeline_in, prev_cut); - if (c->timeline_out < olive::ActiveSequence->playhead) - prev_cut = qMax(c->timeline_out, prev_cut); - } - } + if (c->timeline_in == olive::ActiveSequence->playhead) + playhead_falls_on_in = true; + if (c->timeline_out == olive::ActiveSequence->playhead) + playhead_falls_on_out = true; + if (c->timeline_in > olive::ActiveSequence->playhead) + next_cut = qMin(c->timeline_in, next_cut); + if (c->timeline_out > olive::ActiveSequence->playhead) + next_cut = qMin(c->timeline_out, next_cut); + if (c->timeline_in < olive::ActiveSequence->playhead) + prev_cut = qMax(c->timeline_in, prev_cut); + if (c->timeline_out < olive::ActiveSequence->playhead) + prev_cut = qMax(c->timeline_out, prev_cut); + } + } - next_cut = qMin(sequence_end, next_cut); + next_cut = qMin(sequence_end, next_cut); - QVector areas; - ComboAction* ca = new ComboAction(); - bool push_undo = true; - long seek = olive::ActiveSequence->playhead; + QVector areas; + ComboAction* ca = new ComboAction(); + bool push_undo = true; + long seek = olive::ActiveSequence->playhead; - if ((in && (playhead_falls_on_out || (playhead_falls_on_in && olive::ActiveSequence->playhead == 0))) - || (!in && (playhead_falls_on_in || (playhead_falls_on_out && olive::ActiveSequence->playhead == sequence_end)))) { // one frame mode - if (ripple) { - // set up deletion areas based on track count - long in_point = olive::ActiveSequence->playhead; - if (!in) { - in_point--; - seek--; - } + if ((in && (playhead_falls_on_out || (playhead_falls_on_in && olive::ActiveSequence->playhead == 0))) + || (!in && (playhead_falls_on_in || (playhead_falls_on_out && olive::ActiveSequence->playhead == sequence_end)))) { // one frame mode + if (ripple) { + // set up deletion areas based on track count + long in_point = olive::ActiveSequence->playhead; + if (!in) { + in_point--; + seek--; + } - if (in_point >= 0) { - Selection s; - s.in = in_point; - s.out = in_point + 1; - for (int i=track_min;i<=track_max;i++) { - s.track = i; - areas.append(s); - } + if (in_point >= 0) { + Selection s; + s.in = in_point; + s.out = in_point + 1; + for (int i=track_min;i<=track_max;i++) { + s.track = i; + areas.append(s); + } - // trim and move clips around the in point - delete_areas_and_relink(ca, areas, true); + // trim and move clips around the in point + delete_areas_and_relink(ca, areas, true); - if (ripple) ripple_clips(ca, olive::ActiveSequence, in_point, -1); - } else { - push_undo = false; - } - } else { - push_undo = false; - } - } else { - // set up deletion areas based on track count - Selection s; - if (in) seek = prev_cut; - s.in = in ? prev_cut : olive::ActiveSequence->playhead; - s.out = in ? olive::ActiveSequence->playhead : next_cut; + if (ripple) ripple_clips(ca, olive::ActiveSequence, in_point, -1); + } else { + push_undo = false; + } + } else { + push_undo = false; + } + } else { + // set up deletion areas based on track count + Selection s; + if (in) seek = prev_cut; + s.in = in ? prev_cut : olive::ActiveSequence->playhead; + s.out = in ? olive::ActiveSequence->playhead : next_cut; - if (s.in == s.out) { - push_undo = false; - } else { - for (int i=track_min;i<=track_max;i++) { - s.track = i; - areas.append(s); - } + if (s.in == s.out) { + push_undo = false; + } else { + for (int i=track_min;i<=track_max;i++) { + s.track = i; + areas.append(s); + } - // trim and move clips around the in point - delete_areas_and_relink(ca, areas, true); - if (ripple) ripple_clips(ca, olive::ActiveSequence, s.in, s.in - s.out); - } - } + // trim and move clips around the in point + delete_areas_and_relink(ca, areas, true); + if (ripple) ripple_clips(ca, olive::ActiveSequence, s.in, s.in - s.out); + } + } - if (push_undo) { - olive::UndoStack.push(ca); + if (push_undo) { + olive::UndoStack.push(ca); - update_ui(true); + update_ui(true); - if (seek != olive::ActiveSequence->playhead && ripple) panel_sequence_viewer->seek(seek); - } else { - delete ca; - } - } else { - panel_sequence_viewer->seek(0); - } - } + if (seek != olive::ActiveSequence->playhead && ripple) panel_sequence_viewer->seek(seek); + } else { + delete ca; + } + } else { + panel_sequence_viewer->seek(0); + } + } } bool Timeline::split_selection(ComboAction* ca) { - bool split = false; + bool split = false; - // temporary relinking vectors - QVector pre_splits; - QVector post_splits; - QVector secondary_post_splits; + // temporary relinking vectors + QVector pre_splits; + QVector post_splits; + QVector secondary_post_splits; - // find clips within selection and split - for (int j=0;jclips.size();j++) { - ClipPtr clip = olive::ActiveSequence->clips.at(j); - if (clip != nullptr) { - for (int i=0;iselections.size();i++) { - const Selection& s = olive::ActiveSequence->selections.at(i); - if (s.track == clip->track) { - ClipPtr post_b = split_clip(ca, true, j, s.out); - ClipPtr post_a = split_clip(ca, post_b == nullptr, j, s.in); - pre_splits.append(j); - post_splits.append(post_a); - secondary_post_splits.append(post_b); + // find clips within selection and split + for (int j=0;jclips.size();j++) { + ClipPtr clip = olive::ActiveSequence->clips.at(j); + if (clip != nullptr) { + for (int i=0;iselections.size();i++) { + const Selection& s = olive::ActiveSequence->selections.at(i); + if (s.track == clip->track) { + ClipPtr post_b = split_clip(ca, true, j, s.out); + ClipPtr post_a = split_clip(ca, post_b == nullptr, j, s.in); + pre_splits.append(j); + post_splits.append(post_a); + secondary_post_splits.append(post_b); - if (post_a != nullptr) { - post_a->timeline_out = qMin(post_a->timeline_out, s.out); - } + if (post_a != nullptr) { + post_a->timeline_out = qMin(post_a->timeline_out, s.out); + } - split = true; - } - } - } - } + split = true; + } + } + } + } - if (split) { - // relink after splitting - relink_clips_using_ids(pre_splits, post_splits); - relink_clips_using_ids(pre_splits, secondary_post_splits); + if (split) { + // relink after splitting + relink_clips_using_ids(pre_splits, post_splits); + relink_clips_using_ids(pre_splits, secondary_post_splits); - ca->append(new AddClipCommand(olive::ActiveSequence, post_splits)); - ca->append(new AddClipCommand(olive::ActiveSequence, secondary_post_splits)); + ca->append(new AddClipCommand(olive::ActiveSequence, post_splits)); + ca->append(new AddClipCommand(olive::ActiveSequence, secondary_post_splits)); - return true; - } - return false; + return true; + } + return false; } bool Timeline::split_all_clips_at_point(ComboAction* ca, long point) { - bool split = false; - for (int j=0;jclips.size();j++) { - ClipPtr c = olive::ActiveSequence->clips.at(j); - if (c != nullptr) { - // always relinks - if (split_clip_and_relink(ca, j, point, true)) { - split = true; - } - } - } - return split; + bool split = false; + for (int j=0;jclips.size();j++) { + ClipPtr c = olive::ActiveSequence->clips.at(j); + if (c != nullptr) { + // always relinks + if (split_clip_and_relink(ca, j, point, true)) { + split = true; + } + } + } + return split; } void Timeline::split_at_playhead() { - ComboAction* ca = new ComboAction(); - bool split_selected = false; - split_cache.clear(); + ComboAction* ca = new ComboAction(); + bool split_selected = false; + split_cache.clear(); - if (olive::ActiveSequence->selections.size() > 0) { - // see if whole clips are selected - QVector pre_clips; - QVector post_clips; - for (int j=0;jclips.size();j++) { - ClipPtr clip = olive::ActiveSequence->clips.at(j); - if (clip != nullptr && is_clip_selected(clip, true)) { - ClipPtr s = split_clip(ca, true, j, olive::ActiveSequence->playhead); - if (s != nullptr) { - pre_clips.append(j); - post_clips.append(s); - split_selected = true; - } - } - } - - if (split_selected) { - // relink clips if we split - relink_clips_using_ids(pre_clips, post_clips); - ca->append(new AddClipCommand(olive::ActiveSequence, post_clips)); - } else { - // split a selection if not - split_selected = split_selection(ca); - } - } - - // if nothing was selected or no selections fell within playhead, simply split at playhead - if (!split_selected) { - split_selected = split_all_clips_at_point(ca, olive::ActiveSequence->playhead); - } - - if (split_selected) { - olive::UndoStack.push(ca); - update_ui(true); - } else { - delete ca; + if (olive::ActiveSequence->selections.size() > 0) { + // see if whole clips are selected + QVector pre_clips; + QVector post_clips; + for (int j=0;jclips.size();j++) { + ClipPtr clip = olive::ActiveSequence->clips.at(j); + if (clip != nullptr && is_clip_selected(clip, true)) { + ClipPtr s = split_clip(ca, true, j, olive::ActiveSequence->playhead); + if (s != nullptr) { + pre_clips.append(j); + post_clips.append(s); + split_selected = true; + } + } } + + if (split_selected) { + // relink clips if we split + relink_clips_using_ids(pre_clips, post_clips); + ca->append(new AddClipCommand(olive::ActiveSequence, post_clips)); + } else { + // split a selection if not + split_selected = split_selection(ca); + } + } + + // if nothing was selected or no selections fell within playhead, simply split at playhead + if (!split_selected) { + split_selected = split_all_clips_at_point(ca, olive::ActiveSequence->playhead); + } + + if (split_selected) { + olive::UndoStack.push(ca); + update_ui(true); + } else { + delete ca; + } } void Timeline::ripple_delete() { - if (olive::ActiveSequence != nullptr) { - if (olive::ActiveSequence->selections.size() > 0) { - panel_timeline->delete_selection(olive::ActiveSequence->selections, true); - } else if (olive::CurrentConfig.hover_focus && get_focused_panel() == panel_timeline) { - if (panel_timeline->can_ripple_empty_space(panel_timeline->cursor_frame, panel_timeline->cursor_track)) { - panel_timeline->ripple_delete_empty_space(); - } - } + if (olive::ActiveSequence != nullptr) { + if (olive::ActiveSequence->selections.size() > 0) { + panel_timeline->delete_selection(olive::ActiveSequence->selections, true); + } else if (olive::CurrentConfig.hover_focus && get_focused_panel() == panel_timeline) { + if (panel_timeline->can_ripple_empty_space(panel_timeline->cursor_frame, panel_timeline->cursor_track)) { + panel_timeline->ripple_delete_empty_space(); + } } + } } void Timeline::deselect_area(long in, long out, int track) { - int len = olive::ActiveSequence->selections.size(); - for (int i=0;iselections[i]; - if (s.track == track) { - if (s.in >= in && s.out <= out) { - // whole selection is in deselect area - olive::ActiveSequence->selections.removeAt(i); - i--; - len--; - } else if (s.in < in && s.out > out) { - // middle of selection is in deselect area - Selection new_sel; - new_sel.in = out; - new_sel.out = s.out; - new_sel.track = s.track; - olive::ActiveSequence->selections.append(new_sel); + int len = olive::ActiveSequence->selections.size(); + for (int i=0;iselections[i]; + if (s.track == track) { + if (s.in >= in && s.out <= out) { + // whole selection is in deselect area + olive::ActiveSequence->selections.removeAt(i); + i--; + len--; + } else if (s.in < in && s.out > out) { + // middle of selection is in deselect area + Selection new_sel; + new_sel.in = out; + new_sel.out = s.out; + new_sel.track = s.track; + olive::ActiveSequence->selections.append(new_sel); - s.out = in; - } else if (s.in < in && s.out > in) { - // only out point is in deselect area - s.out = in; - } else if (s.in < out && s.out > out) { - // only in point is in deselect area - s.in = out; - } - } - } + s.out = in; + } else if (s.in < in && s.out > in) { + // only out point is in deselect area + s.out = in; + } else if (s.in < out && s.out > out) { + // only in point is in deselect area + s.in = out; + } + } + } } bool Timeline::snap_to_point(long point, long* l) { - int limit = get_snap_range(); - if (*l > point-limit-1 && *l < point+limit+1) { - snap_point = point; - *l = point; - snapped = true; - return true; - } - return false; + int limit = get_snap_range(); + if (*l > point-limit-1 && *l < point+limit+1) { + snap_point = point; + *l = point; + snapped = true; + return true; + } + return false; } bool Timeline::snap_to_timeline(long* l, bool use_playhead, bool use_markers, bool use_workarea) { - snapped = false; - if (snapping) { - if (use_playhead && !panel_sequence_viewer->playing) { - // snap to playhead - if (snap_to_point(olive::ActiveSequence->playhead, l)) return true; - } + snapped = false; + if (snapping) { + if (use_playhead && !panel_sequence_viewer->playing) { + // snap to playhead + if (snap_to_point(olive::ActiveSequence->playhead, l)) return true; + } - // snap to marker - if (use_markers) { - for (int i=0;imarkers.size();i++) { - if (snap_to_point(olive::ActiveSequence->markers.at(i).frame, l)) return true; - } - } + // snap to marker + if (use_markers) { + for (int i=0;imarkers.size();i++) { + if (snap_to_point(olive::ActiveSequence->markers.at(i).frame, l)) return true; + } + } - // snap to in/out - if (use_workarea && olive::ActiveSequence->using_workarea) { - if (snap_to_point(olive::ActiveSequence->workarea_in, l)) return true; - if (snap_to_point(olive::ActiveSequence->workarea_out, l)) return true; - } + // snap to in/out + if (use_workarea && olive::ActiveSequence->using_workarea) { + if (snap_to_point(olive::ActiveSequence->workarea_in, l)) return true; + if (snap_to_point(olive::ActiveSequence->workarea_out, l)) return true; + } - // snap to clip/transition - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr) { - if (snap_to_point(c->timeline_in, l)) { - return true; - } else if (snap_to_point(c->timeline_out, l)) { - return true; - } else if (c->get_opening_transition() != nullptr - && snap_to_point(c->timeline_in + c->get_opening_transition()->get_true_length(), l)) { - return true; - } else if (c->get_closing_transition() != nullptr - && snap_to_point(c->timeline_out - c->get_closing_transition()->get_true_length(), l)) { - return true; - } else { - // try to snap to clip markers - for (int j=0;jget_markers().size();j++) { - if (snap_to_point(c->get_markers().at(j).frame + c->timeline_in - c->clip_in, l)) { - return true; - } - } - } - } - } - } - return false; + // snap to clip/transition + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr) { + if (snap_to_point(c->timeline_in, l)) { + return true; + } else if (snap_to_point(c->timeline_out, l)) { + return true; + } else if (c->get_opening_transition() != nullptr + && snap_to_point(c->timeline_in + c->get_opening_transition()->get_true_length(), l)) { + return true; + } else if (c->get_closing_transition() != nullptr + && snap_to_point(c->timeline_out - c->get_closing_transition()->get_true_length(), l)) { + return true; + } else { + // try to snap to clip markers + for (int j=0;jget_markers().size();j++) { + if (snap_to_point(c->get_markers().at(j).frame + c->timeline_in - c->clip_in, l)) { + return true; + } + } + } + } + } + } + return false; } void Timeline::set_marker() { - // determine if any clips are selected, and if so add markers to clips rather than the sequence - QVector clips_selected; - bool clip_mode = false; + // determine if any clips are selected, and if so add markers to clips rather than the sequence + QVector clips_selected; + bool clip_mode = false; - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr - && is_clip_selected(c, true)) { + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr + && is_clip_selected(c, true)) { - // only add markers if the playhead is inside the clip - if (olive::ActiveSequence->playhead >= c->timeline_in - && olive::ActiveSequence->playhead <= c->timeline_out) { - clips_selected.append(i); - } + // only add markers if the playhead is inside the clip + if (olive::ActiveSequence->playhead >= c->timeline_in + && olive::ActiveSequence->playhead <= c->timeline_out) { + clips_selected.append(i); + } - // we are definitely adding markers to clips though - clip_mode = true; + // we are definitely adding markers to clips though + clip_mode = true; - } - } + } + } - // if we've selected clips but none of the clips are within the playhead, - // nothing to do here - if (clip_mode && clips_selected.size() == 0) { - return; - } + // if we've selected clips but none of the clips are within the playhead, + // nothing to do here + if (clip_mode && clips_selected.size() == 0) { + return; + } - // pass off to internal set marker function - set_marker_internal(olive::ActiveSequence, clips_selected); + // pass off to internal set marker function + set_marker_internal(olive::ActiveSequence, clips_selected); } void Timeline::delete_inout() { - panel_timeline->delete_in_out_internal(false); + panel_timeline->delete_in_out_internal(false); } void Timeline::ripple_delete_inout() { - panel_timeline->delete_in_out_internal(true); + panel_timeline->delete_in_out_internal(true); } void Timeline::ripple_to_in_point() { - panel_timeline->edit_to_point_internal(true, true); + panel_timeline->edit_to_point_internal(true, true); } void Timeline::ripple_to_out_point() { - panel_timeline->edit_to_point_internal(false, true); + panel_timeline->edit_to_point_internal(false, true); } void Timeline::edit_to_in_point() { - panel_timeline->edit_to_point_internal(true, false); + panel_timeline->edit_to_point_internal(true, false); } void Timeline::edit_to_out_point() { - panel_timeline->edit_to_point_internal(false, false); + panel_timeline->edit_to_point_internal(false, false); } void Timeline::toggle_links() { - LinkCommand* command = new LinkCommand(); - command->s = olive::ActiveSequence; - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr && is_clip_selected(c, true)) { - if (!command->clips.contains(i)) command->clips.append(i); + LinkCommand* command = new LinkCommand(); + command->s = olive::ActiveSequence; + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr && is_clip_selected(c, true)) { + if (!command->clips.contains(i)) command->clips.append(i); - if (c->linked.size() > 0) { - command->link = false; // prioritize unlinking + if (c->linked.size() > 0) { + command->link = false; // prioritize unlinking - for (int j=0;jlinked.size();j++) { // add links to the command - if (!command->clips.contains(c->linked.at(j))) command->clips.append(c->linked.at(j)); - } - } - } - } - if (command->clips.size() > 0) { - olive::UndoStack.push(command); - repaint_timeline(); - } else { - delete command; - } + for (int j=0;jlinked.size();j++) { // add links to the command + if (!command->clips.contains(c->linked.at(j))) command->clips.append(c->linked.at(j)); + } + } + } + } + if (command->clips.size() > 0) { + olive::UndoStack.push(command); + repaint_timeline(); + } else { + delete command; + } } void Timeline::increase_track_height() { - for (int i=0;iselections.clear(); - repaint_timeline(); + olive::ActiveSequence->selections.clear(); + repaint_timeline(); } long getFrameFromScreenPoint(double zoom, int x) { - long f = qCeil(double(x) / zoom); - if (f < 0) { - return 0; - } - return f; + long f = qCeil(double(x) / zoom); + if (f < 0) { + return 0; + } + return f; } int getScreenPointFromFrame(double zoom, long frame) { - return qFloor(double(frame)*zoom); + return qFloor(double(frame)*zoom); } long Timeline::getTimelineFrameFromScreenPoint(int x) { - return getFrameFromScreenPoint(zoom, x + scroll); + return getFrameFromScreenPoint(zoom, x + scroll); } int Timeline::getTimelineScreenPointFromFrame(long frame) { - return getScreenPointFromFrame(zoom, frame) - scroll; + return getScreenPointFromFrame(zoom, frame) - scroll; } void Timeline::add_btn_click() { - QMenu add_menu(this); + QMenu add_menu(this); - QAction* titleMenuItem = new QAction(&add_menu); - titleMenuItem->setText(tr("Title...")); - titleMenuItem->setData(ADD_OBJ_TITLE); - add_menu.addAction(titleMenuItem); + QAction* titleMenuItem = new QAction(&add_menu); + titleMenuItem->setText(tr("Title...")); + titleMenuItem->setData(ADD_OBJ_TITLE); + add_menu.addAction(titleMenuItem); - QAction* solidMenuItem = new QAction(&add_menu); - solidMenuItem->setText(tr("Solid Color...")); - solidMenuItem->setData(ADD_OBJ_SOLID); - add_menu.addAction(solidMenuItem); + QAction* solidMenuItem = new QAction(&add_menu); + solidMenuItem->setText(tr("Solid Color...")); + solidMenuItem->setData(ADD_OBJ_SOLID); + add_menu.addAction(solidMenuItem); - QAction* barsMenuItem = new QAction(&add_menu); - barsMenuItem->setText(tr("Bars...")); - barsMenuItem->setData(ADD_OBJ_BARS); - add_menu.addAction(barsMenuItem); + QAction* barsMenuItem = new QAction(&add_menu); + barsMenuItem->setText(tr("Bars...")); + barsMenuItem->setData(ADD_OBJ_BARS); + add_menu.addAction(barsMenuItem); - add_menu.addSeparator(); + add_menu.addSeparator(); - QAction* toneMenuItem = new QAction(&add_menu); - toneMenuItem->setText(tr("Tone...")); - toneMenuItem->setData(ADD_OBJ_TONE); - add_menu.addAction(toneMenuItem); + QAction* toneMenuItem = new QAction(&add_menu); + toneMenuItem->setText(tr("Tone...")); + toneMenuItem->setData(ADD_OBJ_TONE); + add_menu.addAction(toneMenuItem); - QAction* noiseMenuItem = new QAction(&add_menu); - noiseMenuItem->setText(tr("Noise...")); - noiseMenuItem->setData(ADD_OBJ_NOISE); - add_menu.addAction(noiseMenuItem); + QAction* noiseMenuItem = new QAction(&add_menu); + noiseMenuItem->setText(tr("Noise...")); + noiseMenuItem->setData(ADD_OBJ_NOISE); + add_menu.addAction(noiseMenuItem); - connect(&add_menu, SIGNAL(triggered(QAction*)), this, SLOT(add_menu_item(QAction*))); + connect(&add_menu, SIGNAL(triggered(QAction*)), this, SLOT(add_menu_item(QAction*))); - add_menu.exec(QCursor::pos()); + add_menu.exec(QCursor::pos()); } void Timeline::add_menu_item(QAction* action) { - creating = true; - creating_object = action->data().toInt(); + creating = true; + creating_object = action->data().toInt(); } void Timeline::setScroll(int s) { - scroll = s; - headers->set_scroll(s); - repaint_timeline(); + scroll = s; + headers->set_scroll(s); + repaint_timeline(); } void Timeline::record_btn_click() { - if (olive::ActiveProjectFilename.isEmpty()) { - QMessageBox::critical(this, - tr("Unsaved Project"), - tr("You must save this project before you can record audio in it."), - QMessageBox::Ok); - } else { - creating = true; - creating_object = ADD_OBJ_AUDIO; - olive::MainWindow->statusBar()->showMessage( - tr("Click on the timeline where you want to start recording (drag to limit the recording to a certain timeframe)"), - 10000); - } + if (olive::ActiveProjectFilename.isEmpty()) { + QMessageBox::critical(this, + tr("Unsaved Project"), + tr("You must save this project before you can record audio in it."), + QMessageBox::Ok); + } else { + creating = true; + creating_object = ADD_OBJ_AUDIO; + olive::MainWindow->statusBar()->showMessage( + tr("Click on the timeline where you want to start recording (drag to limit the recording to a certain timeframe)"), + 10000); + } } void Timeline::transition_tool_click() { - creating = false; + creating = false; - QMenu transition_menu(this); + QMenu transition_menu(this); - for (int i=0;isetObjectName("v"); - a->setData(reinterpret_cast(&em)); - } - } + for (int i=0;isetObjectName("v"); + a->setData(reinterpret_cast(&em)); + } + } - transition_menu.addSeparator(); + transition_menu.addSeparator(); - for (int i=0;isetObjectName("a"); - a->setData(reinterpret_cast(&em)); - } - } + for (int i=0;isetObjectName("a"); + a->setData(reinterpret_cast(&em)); + } + } - connect(&transition_menu, SIGNAL(triggered(QAction*)), this, SLOT(transition_menu_select(QAction*))); + connect(&transition_menu, SIGNAL(triggered(QAction*)), this, SLOT(transition_menu_select(QAction*))); - toolTransitionButton->setChecked(false); + toolTransitionButton->setChecked(false); - transition_menu.exec(QCursor::pos()); + transition_menu.exec(QCursor::pos()); } void Timeline::transition_menu_select(QAction* a) { - transition_tool_meta = reinterpret_cast(a->data().value()); + transition_tool_meta = reinterpret_cast(a->data().value()); - if (a->objectName() == "v") { - transition_tool_side = -1; - } else { - transition_tool_side = 1; - } + if (a->objectName() == "v") { + transition_tool_side = -1; + } else { + transition_tool_side = 1; + } - decheck_tool_buttons(sender()); - timeline_area->setCursor(Qt::CrossCursor); - tool = TIMELINE_TOOL_TRANSITION; - toolTransitionButton->setChecked(true); + decheck_tool_buttons(sender()); + timeline_area->setCursor(Qt::CrossCursor); + tool = TIMELINE_TOOL_TRANSITION; + toolTransitionButton->setChecked(true); } void Timeline::resize_move(double z) { - set_zoom_value(zoom * z); + set_zoom_value(zoom * z); } void Timeline::set_sb_max() { - headers->set_scrollbar_max(horizontalScrollBar, olive::ActiveSequence->getEndFrame(), editAreas->width() - getScreenPointFromFrame(zoom, 200)); + headers->set_scrollbar_max(horizontalScrollBar, olive::ActiveSequence->getEndFrame(), editAreas->width() - getScreenPointFromFrame(zoom, 200)); +} + +void Timeline::UpdateTitle() { + QString title = tr("Timeline: "); + if (olive::ActiveSequence == nullptr) { + setWindowTitle(title + tr("")); + } else { + setWindowTitle(title + olive::ActiveSequence->name); + update_ui(false); + } } void Timeline::setup_ui() { - QWidget* dockWidgetContents = new QWidget(); + QWidget* dockWidgetContents = new QWidget(); - QHBoxLayout* horizontalLayout = new QHBoxLayout(dockWidgetContents); - horizontalLayout->setSpacing(0); - horizontalLayout->setMargin(0); + QHBoxLayout* horizontalLayout = new QHBoxLayout(dockWidgetContents); + horizontalLayout->setSpacing(0); + horizontalLayout->setMargin(0); - setWidget(dockWidgetContents); + setWidget(dockWidgetContents); - tool_button_widget = new QWidget(); - tool_button_widget->setObjectName("timeline_toolbar"); - tool_button_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + tool_button_widget = new QWidget(); + tool_button_widget->setObjectName("timeline_toolbar"); + tool_button_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - FlowLayout* tool_buttons_layout = new FlowLayout(tool_button_widget); - tool_buttons_layout->setSpacing(4); - tool_buttons_layout->setMargin(0); + FlowLayout* tool_buttons_layout = new FlowLayout(tool_button_widget); + tool_buttons_layout->setSpacing(4); + tool_buttons_layout->setMargin(0); - toolArrowButton = new QPushButton(); - QIcon arrow_icon; - arrow_icon.addFile(QStringLiteral(":/icons/arrow.png"), QSize(), QIcon::Normal, QIcon::Off); - arrow_icon.addFile(QStringLiteral(":/icons/arrow-disabled.png"), QSize(), QIcon::Disabled, QIcon::Off); - toolArrowButton->setIcon(arrow_icon); - toolArrowButton->setCheckable(true); - toolArrowButton->setToolTip(tr("Pointer Tool") + " (V)"); - toolArrowButton->setProperty("tool", TIMELINE_TOOL_POINTER); - connect(toolArrowButton, SIGNAL(clicked(bool)), this, SLOT(set_tool())); - tool_buttons_layout->addWidget(toolArrowButton); + toolArrowButton = new QPushButton(); + QIcon arrow_icon; + arrow_icon.addFile(QStringLiteral(":/icons/arrow.png"), QSize(), QIcon::Normal, QIcon::Off); + arrow_icon.addFile(QStringLiteral(":/icons/arrow-disabled.png"), QSize(), QIcon::Disabled, QIcon::Off); + toolArrowButton->setIcon(arrow_icon); + toolArrowButton->setCheckable(true); + toolArrowButton->setProperty("tool", TIMELINE_TOOL_POINTER); + connect(toolArrowButton, SIGNAL(clicked(bool)), this, SLOT(set_tool())); + tool_buttons_layout->addWidget(toolArrowButton); - toolEditButton = new QPushButton(); - QIcon icon1; - icon1.addFile(QStringLiteral(":/icons/beam.png"), QSize(), QIcon::Normal, QIcon::Off); - icon1.addFile(QStringLiteral(":/icons/beam-disabled.png"), QSize(), QIcon::Disabled, QIcon::Off); - toolEditButton->setIcon(icon1); - toolEditButton->setCheckable(true); - toolEditButton->setToolTip(tr("Edit Tool") + " (X)"); - toolEditButton->setProperty("tool", TIMELINE_TOOL_EDIT); - connect(toolEditButton, SIGNAL(clicked(bool)), this, SLOT(set_tool())); - tool_buttons_layout->addWidget(toolEditButton); + toolEditButton = new QPushButton(); + QIcon icon1; + icon1.addFile(QStringLiteral(":/icons/beam.png"), QSize(), QIcon::Normal, QIcon::Off); + icon1.addFile(QStringLiteral(":/icons/beam-disabled.png"), QSize(), QIcon::Disabled, QIcon::Off); + toolEditButton->setIcon(icon1); + toolEditButton->setCheckable(true); + toolEditButton->setProperty("tool", TIMELINE_TOOL_EDIT); + connect(toolEditButton, SIGNAL(clicked(bool)), this, SLOT(set_tool())); + tool_buttons_layout->addWidget(toolEditButton); - toolRippleButton = new QPushButton(); - QIcon icon2; - icon2.addFile(QStringLiteral(":/icons/ripple.png"), QSize(), QIcon::Normal, QIcon::Off); - icon2.addFile(QStringLiteral(":/icons/ripple-disabled.png"), QSize(), QIcon::Disabled, QIcon::Off); - toolRippleButton->setIcon(icon2); - toolRippleButton->setCheckable(true); - toolRippleButton->setToolTip(tr("Ripple Tool") + " (B)"); - toolRippleButton->setProperty("tool", TIMELINE_TOOL_RIPPLE); - connect(toolRippleButton, SIGNAL(clicked(bool)), this, SLOT(set_tool())); - tool_buttons_layout->addWidget(toolRippleButton); + toolRippleButton = new QPushButton(); + QIcon icon2; + icon2.addFile(QStringLiteral(":/icons/ripple.png"), QSize(), QIcon::Normal, QIcon::Off); + icon2.addFile(QStringLiteral(":/icons/ripple-disabled.png"), QSize(), QIcon::Disabled, QIcon::Off); + toolRippleButton->setIcon(icon2); + toolRippleButton->setCheckable(true); + toolRippleButton->setProperty("tool", TIMELINE_TOOL_RIPPLE); + connect(toolRippleButton, SIGNAL(clicked(bool)), this, SLOT(set_tool())); + tool_buttons_layout->addWidget(toolRippleButton); - toolRazorButton = new QPushButton(); - QIcon icon4; - icon4.addFile(QStringLiteral(":/icons/razor.png"), QSize(), QIcon::Normal, QIcon::Off); - icon4.addFile(QStringLiteral(":/icons/razor-disabled.png"), QSize(), QIcon::Disabled, QIcon::Off); - toolRazorButton->setIcon(icon4); - toolRazorButton->setCheckable(true); - toolRazorButton->setToolTip(tr("Razor Tool") + " (C)"); - toolRazorButton->setProperty("tool", TIMELINE_TOOL_RAZOR); - connect(toolRazorButton, SIGNAL(clicked(bool)), this, SLOT(set_tool())); - tool_buttons_layout->addWidget(toolRazorButton); + toolRazorButton = new QPushButton(); + QIcon icon4; + icon4.addFile(QStringLiteral(":/icons/razor.png"), QSize(), QIcon::Normal, QIcon::Off); + icon4.addFile(QStringLiteral(":/icons/razor-disabled.png"), QSize(), QIcon::Disabled, QIcon::Off); + toolRazorButton->setIcon(icon4); + toolRazorButton->setCheckable(true); + toolRazorButton->setProperty("tool", TIMELINE_TOOL_RAZOR); + connect(toolRazorButton, SIGNAL(clicked(bool)), this, SLOT(set_tool())); + tool_buttons_layout->addWidget(toolRazorButton); - toolSlipButton = new QPushButton(); - QIcon icon5; - icon5.addFile(QStringLiteral(":/icons/slip.png"), QSize(), QIcon::Normal, QIcon::On); - icon5.addFile(QStringLiteral(":/icons/slip-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); - toolSlipButton->setIcon(icon5); - toolSlipButton->setCheckable(true); - toolSlipButton->setToolTip(tr("Slip Tool") + " (Y)"); - toolSlipButton->setProperty("tool", TIMELINE_TOOL_SLIP); - connect(toolSlipButton, SIGNAL(clicked(bool)), this, SLOT(set_tool())); - tool_buttons_layout->addWidget(toolSlipButton); + toolSlipButton = new QPushButton(); + QIcon icon5; + icon5.addFile(QStringLiteral(":/icons/slip.png"), QSize(), QIcon::Normal, QIcon::On); + icon5.addFile(QStringLiteral(":/icons/slip-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); + toolSlipButton->setIcon(icon5); + toolSlipButton->setCheckable(true); + toolSlipButton->setProperty("tool", TIMELINE_TOOL_SLIP); + connect(toolSlipButton, SIGNAL(clicked(bool)), this, SLOT(set_tool())); + tool_buttons_layout->addWidget(toolSlipButton); - toolSlideButton = new QPushButton(); - QIcon icon6; - icon6.addFile(QStringLiteral(":/icons/slide.png"), QSize(), QIcon::Normal, QIcon::On); - icon6.addFile(QStringLiteral(":/icons/slide-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); - toolSlideButton->setIcon(icon6); - toolSlideButton->setCheckable(true); - toolSlideButton->setToolTip(tr("Slide Tool") + " (U)"); - toolSlideButton->setProperty("tool", TIMELINE_TOOL_SLIDE); - connect(toolSlideButton, SIGNAL(clicked(bool)), this, SLOT(set_tool())); - tool_buttons_layout->addWidget(toolSlideButton); + toolSlideButton = new QPushButton(); + QIcon icon6; + icon6.addFile(QStringLiteral(":/icons/slide.png"), QSize(), QIcon::Normal, QIcon::On); + icon6.addFile(QStringLiteral(":/icons/slide-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); + toolSlideButton->setIcon(icon6); + toolSlideButton->setCheckable(true); + toolSlideButton->setProperty("tool", TIMELINE_TOOL_SLIDE); + connect(toolSlideButton, SIGNAL(clicked(bool)), this, SLOT(set_tool())); + tool_buttons_layout->addWidget(toolSlideButton); - toolHandButton = new QPushButton(); - QIcon icon7; - icon7.addFile(QStringLiteral(":/icons/hand.png"), QSize(), QIcon::Normal, QIcon::On); - icon7.addFile(QStringLiteral(":/icons/hand-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); - toolHandButton->setIcon(icon7); - toolHandButton->setCheckable(true); - toolHandButton->setToolTip(tr("Hand Tool") + " (H)"); - toolHandButton->setProperty("tool", TIMELINE_TOOL_HAND); - connect(toolHandButton, SIGNAL(clicked(bool)), this, SLOT(set_tool())); - tool_buttons_layout->addWidget(toolHandButton); + toolHandButton = new QPushButton(); + QIcon icon7; + icon7.addFile(QStringLiteral(":/icons/hand.png"), QSize(), QIcon::Normal, QIcon::On); + icon7.addFile(QStringLiteral(":/icons/hand-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); + toolHandButton->setIcon(icon7); + toolHandButton->setCheckable(true); - toolTransitionButton = new QPushButton(); - QIcon icon8; - icon8.addFile(QStringLiteral(":/icons/transition-tool.png"), QSize(), QIcon::Normal, QIcon::On); - icon8.addFile(QStringLiteral(":/icons/transition-tool-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); - toolTransitionButton->setIcon(icon8); - toolTransitionButton->setCheckable(true); - toolTransitionButton->setToolTip(tr("Transition Tool") + " (T)"); - connect(toolTransitionButton, SIGNAL(clicked(bool)), this, SLOT(transition_tool_click())); - tool_buttons_layout->addWidget(toolTransitionButton); + toolHandButton->setProperty("tool", TIMELINE_TOOL_HAND); + connect(toolHandButton, SIGNAL(clicked(bool)), this, SLOT(set_tool())); + tool_buttons_layout->addWidget(toolHandButton); + toolTransitionButton = new QPushButton(); + QIcon icon8; + icon8.addFile(QStringLiteral(":/icons/transition-tool.png"), QSize(), QIcon::Normal, QIcon::On); + icon8.addFile(QStringLiteral(":/icons/transition-tool-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); + toolTransitionButton->setIcon(icon8); + toolTransitionButton->setCheckable(true); + connect(toolTransitionButton, SIGNAL(clicked(bool)), this, SLOT(transition_tool_click())); + tool_buttons_layout->addWidget(toolTransitionButton); - snappingButton = new QPushButton(); - QIcon icon9; - icon9.addFile(QStringLiteral(":/icons/magnet.png"), QSize(), QIcon::Normal, QIcon::On); - icon9.addFile(QStringLiteral(":/icons/magnet-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); - snappingButton->setIcon(icon9); - snappingButton->setCheckable(true); - snappingButton->setChecked(true); - snappingButton->setToolTip(tr("Snapping") + " (S)"); - connect(snappingButton, SIGNAL(toggled(bool)), this, SLOT(snapping_clicked(bool))); - tool_buttons_layout->addWidget(snappingButton); + snappingButton = new QPushButton(); + QIcon icon9; + icon9.addFile(QStringLiteral(":/icons/magnet.png"), QSize(), QIcon::Normal, QIcon::On); + icon9.addFile(QStringLiteral(":/icons/magnet-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); + snappingButton->setIcon(icon9); + snappingButton->setCheckable(true); + snappingButton->setChecked(true); + connect(snappingButton, SIGNAL(toggled(bool)), this, SLOT(snapping_clicked(bool))); + tool_buttons_layout->addWidget(snappingButton); - zoomInButton = new QPushButton(); - QIcon icon10; - icon10.addFile(QStringLiteral(":/icons/zoomin.png"), QSize(), QIcon::Normal, QIcon::On); - icon10.addFile(QStringLiteral(":/icons/zoomin-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); - zoomInButton->setIcon(icon10); - zoomInButton->setToolTip(tr("Zoom In") + " (=)"); - connect(zoomInButton, SIGNAL(clicked(bool)), this, SLOT(zoom_in())); - tool_buttons_layout->addWidget(zoomInButton); + zoomInButton = new QPushButton(); + QIcon icon10; + icon10.addFile(QStringLiteral(":/icons/zoomin.png"), QSize(), QIcon::Normal, QIcon::On); + icon10.addFile(QStringLiteral(":/icons/zoomin-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); + zoomInButton->setIcon(icon10); + connect(zoomInButton, SIGNAL(clicked(bool)), this, SLOT(zoom_in())); + tool_buttons_layout->addWidget(zoomInButton); - zoomOutButton = new QPushButton(); - QIcon icon11; - icon11.addFile(QStringLiteral(":/icons/zoomout.png"), QSize(), QIcon::Normal, QIcon::On); - icon11.addFile(QStringLiteral(":/icons/zoomout-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); - zoomOutButton->setIcon(icon11); - zoomOutButton->setToolTip(tr("Zoom Out") + " (-)"); - connect(zoomOutButton, SIGNAL(clicked(bool)), this, SLOT(zoom_out())); - tool_buttons_layout->addWidget(zoomOutButton); + zoomOutButton = new QPushButton(); + QIcon icon11; + icon11.addFile(QStringLiteral(":/icons/zoomout.png"), QSize(), QIcon::Normal, QIcon::On); + icon11.addFile(QStringLiteral(":/icons/zoomout-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); + zoomOutButton->setIcon(icon11); + connect(zoomOutButton, SIGNAL(clicked(bool)), this, SLOT(zoom_out())); + tool_buttons_layout->addWidget(zoomOutButton); - recordButton = new QPushButton(); - QIcon icon12; - icon12.addFile(QStringLiteral(":/icons/record.png"), QSize(), QIcon::Normal, QIcon::On); - icon12.addFile(QStringLiteral(":/icons/record-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); - recordButton->setIcon(icon12); - recordButton->setToolTip(tr("Record audio")); - connect(recordButton, SIGNAL(clicked(bool)), this, SLOT(record_btn_click())); - tool_buttons_layout->addWidget(recordButton); + recordButton = new QPushButton(); + QIcon icon12; + icon12.addFile(QStringLiteral(":/icons/record.png"), QSize(), QIcon::Normal, QIcon::On); + icon12.addFile(QStringLiteral(":/icons/record-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); + recordButton->setIcon(icon12); + connect(recordButton, SIGNAL(clicked(bool)), this, SLOT(record_btn_click())); + tool_buttons_layout->addWidget(recordButton); - addButton = new QPushButton(); - QIcon icon13; - icon13.addFile(QStringLiteral(":/icons/add-button.png"), QSize(), QIcon::Normal, QIcon::On); - icon13.addFile(QStringLiteral(":/icons/add-button-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); - addButton->setIcon(icon13); - addButton->setToolTip(tr("Add title, solid, bars, etc.")); - connect(addButton, SIGNAL(clicked()), this, SLOT(add_btn_click())); - tool_buttons_layout->addWidget(addButton); + addButton = new QPushButton(); + QIcon icon13; + icon13.addFile(QStringLiteral(":/icons/add-button.png"), QSize(), QIcon::Normal, QIcon::On); + icon13.addFile(QStringLiteral(":/icons/add-button-disabled.png"), QSize(), QIcon::Disabled, QIcon::On); + addButton->setIcon(icon13); + connect(addButton, SIGNAL(clicked()), this, SLOT(add_btn_click())); + tool_buttons_layout->addWidget(addButton); - horizontalLayout->addWidget(tool_button_widget); + horizontalLayout->addWidget(tool_button_widget); - timeline_area = new QWidget(); - QSizePolicy timeline_area_policy(QSizePolicy::Minimum, QSizePolicy::Minimum); - timeline_area_policy.setHorizontalStretch(1); - timeline_area_policy.setVerticalStretch(0); - timeline_area_policy.setHeightForWidth(timeline_area->sizePolicy().hasHeightForWidth()); - timeline_area->setSizePolicy(timeline_area_policy); + timeline_area = new QWidget(); + QSizePolicy timeline_area_policy(QSizePolicy::Minimum, QSizePolicy::Minimum); + timeline_area_policy.setHorizontalStretch(1); + timeline_area_policy.setVerticalStretch(0); + timeline_area_policy.setHeightForWidth(timeline_area->sizePolicy().hasHeightForWidth()); + timeline_area->setSizePolicy(timeline_area_policy); - QVBoxLayout* timeline_area_layout = new QVBoxLayout(timeline_area); - timeline_area_layout->setSpacing(0); - timeline_area_layout->setContentsMargins(0, 0, 0, 0); + QVBoxLayout* timeline_area_layout = new QVBoxLayout(timeline_area); + timeline_area_layout->setSpacing(0); + timeline_area_layout->setContentsMargins(0, 0, 0, 0); - headers = new TimelineHeader(); - timeline_area_layout->addWidget(headers); + headers = new TimelineHeader(); + timeline_area_layout->addWidget(headers); - editAreas = new QWidget(); - QHBoxLayout* editAreaLayout = new QHBoxLayout(editAreas); - editAreaLayout->setSpacing(0); - editAreaLayout->setContentsMargins(0, 0, 0, 0); + editAreas = new QWidget(); + QHBoxLayout* editAreaLayout = new QHBoxLayout(editAreas); + editAreaLayout->setSpacing(0); + editAreaLayout->setContentsMargins(0, 0, 0, 0); - QSplitter* splitter = new QSplitter(); - splitter->setChildrenCollapsible(false); - splitter->setOrientation(Qt::Vertical); + QSplitter* splitter = new QSplitter(); + splitter->setChildrenCollapsible(false); + splitter->setOrientation(Qt::Vertical); - QWidget* videoContainer = new QWidget(); + QWidget* videoContainer = new QWidget(); - QHBoxLayout* videoContainerLayout = new QHBoxLayout(videoContainer); - videoContainerLayout->setSpacing(0); - videoContainerLayout->setContentsMargins(0, 0, 0, 0); + QHBoxLayout* videoContainerLayout = new QHBoxLayout(videoContainer); + videoContainerLayout->setSpacing(0); + videoContainerLayout->setContentsMargins(0, 0, 0, 0); - video_area = new TimelineWidget(); - video_area->setFocusPolicy(Qt::ClickFocus); - videoContainerLayout->addWidget(video_area); + video_area = new TimelineWidget(); + video_area->setFocusPolicy(Qt::ClickFocus); + videoContainerLayout->addWidget(video_area); - videoScrollbar = new QScrollBar(); - videoScrollbar->setMaximum(0); - videoScrollbar->setSingleStep(20); - videoScrollbar->setOrientation(Qt::Vertical); - videoContainerLayout->addWidget(videoScrollbar); + videoScrollbar = new QScrollBar(); + videoScrollbar->setMaximum(0); + videoScrollbar->setSingleStep(20); + videoScrollbar->setOrientation(Qt::Vertical); + videoContainerLayout->addWidget(videoScrollbar); - splitter->addWidget(videoContainer); + splitter->addWidget(videoContainer); - QWidget* audioContainer = new QWidget(); - QHBoxLayout* audioContainerLayout = new QHBoxLayout(audioContainer); - audioContainerLayout->setSpacing(0); - audioContainerLayout->setContentsMargins(0, 0, 0, 0); + QWidget* audioContainer = new QWidget(); + QHBoxLayout* audioContainerLayout = new QHBoxLayout(audioContainer); + audioContainerLayout->setSpacing(0); + audioContainerLayout->setContentsMargins(0, 0, 0, 0); - audio_area = new TimelineWidget(); - audio_area->setFocusPolicy(Qt::ClickFocus); + audio_area = new TimelineWidget(); + audio_area->setFocusPolicy(Qt::ClickFocus); - audioContainerLayout->addWidget(audio_area); + audioContainerLayout->addWidget(audio_area); - audioScrollbar = new QScrollBar(); - audioScrollbar->setMaximum(0); - audioScrollbar->setOrientation(Qt::Vertical); + audioScrollbar = new QScrollBar(); + audioScrollbar->setMaximum(0); + audioScrollbar->setOrientation(Qt::Vertical); - audioContainerLayout->addWidget(audioScrollbar); + audioContainerLayout->addWidget(audioScrollbar); - splitter->addWidget(audioContainer); + splitter->addWidget(audioContainer); - editAreaLayout->addWidget(splitter); + editAreaLayout->addWidget(splitter); - timeline_area_layout->addWidget(editAreas); + timeline_area_layout->addWidget(editAreas); - horizontalScrollBar = new ResizableScrollBar(); - horizontalScrollBar->setMaximum(0); - horizontalScrollBar->setSingleStep(20); - horizontalScrollBar->setOrientation(Qt::Horizontal); + horizontalScrollBar = new ResizableScrollBar(); + horizontalScrollBar->setMaximum(0); + horizontalScrollBar->setSingleStep(20); + horizontalScrollBar->setOrientation(Qt::Horizontal); - timeline_area_layout->addWidget(horizontalScrollBar); + timeline_area_layout->addWidget(horizontalScrollBar); - horizontalLayout->addWidget(timeline_area); + horizontalLayout->addWidget(timeline_area); - audio_monitor = new AudioMonitor(); - audio_monitor->setMinimumSize(QSize(50, 0)); + audio_monitor = new AudioMonitor(); + audio_monitor->setMinimumSize(QSize(50, 0)); - horizontalLayout->addWidget(audio_monitor); + horizontalLayout->addWidget(audio_monitor); - setWidget(dockWidgetContents); + setWidget(dockWidgetContents); } void move_clip(ComboAction* ca, ClipPtr c, long iin, long iout, long iclip_in, int itrack, bool verify_transitions, bool relative) { - ca->append(new MoveClipAction(c, iin, iout, iclip_in, itrack, relative)); + ca->append(new MoveClipAction(c, iin, iout, iclip_in, itrack, relative)); - if (verify_transitions) { - if (c->get_opening_transition() != nullptr && c->get_opening_transition()->secondary_clip != nullptr && c->get_opening_transition()->secondary_clip->timeline_out != iin) { - // separate transition - ca->append(new SetPointer(reinterpret_cast(&c->get_opening_transition()->secondary_clip), nullptr)); + if (verify_transitions) { + if (c->get_opening_transition() != nullptr && c->get_opening_transition()->secondary_clip != nullptr && c->get_opening_transition()->secondary_clip->timeline_out != iin) { + // separate transition + ca->append(new SetPointer(reinterpret_cast(&c->get_opening_transition()->secondary_clip), nullptr)); ca->append(new AddTransitionCommand(c->get_opening_transition()->secondary_clip, nullptr, c->get_opening_transition(), nullptr, kTransitionClosing, 0)); - } + } - if (c->get_closing_transition() != nullptr && c->get_closing_transition()->secondary_clip != nullptr && c->get_closing_transition()->parent_clip->timeline_in != iout) { - // separate transition - ca->append(new SetPointer(reinterpret_cast(&c->get_closing_transition()->secondary_clip), nullptr)); + if (c->get_closing_transition() != nullptr && c->get_closing_transition()->secondary_clip != nullptr && c->get_closing_transition()->parent_clip->timeline_in != iout) { + // separate transition + ca->append(new SetPointer(reinterpret_cast(&c->get_closing_transition()->secondary_clip), nullptr)); ca->append(new AddTransitionCommand(c, nullptr, c->get_closing_transition(), nullptr, kTransitionClosing, 0)); - } - } + } + } } void Timeline::set_tool() { - QPushButton* button = static_cast(sender()); - decheck_tool_buttons(button); - tool = button->property("tool").toInt(); - creating = false; - switch (tool) { - case TIMELINE_TOOL_EDIT: - case TIMELINE_TOOL_RAZOR: - timeline_area->setCursor(Qt::IBeamCursor); - break; - case TIMELINE_TOOL_HAND: - timeline_area->setCursor(Qt::OpenHandCursor); - break; - default: - timeline_area->setCursor(Qt::ArrowCursor); - } + QPushButton* button = static_cast(sender()); + decheck_tool_buttons(button); + tool = button->property("tool").toInt(); + creating = false; + switch (tool) { + case TIMELINE_TOOL_EDIT: + case TIMELINE_TOOL_RAZOR: + timeline_area->setCursor(Qt::IBeamCursor); + break; + case TIMELINE_TOOL_HAND: + timeline_area->setCursor(Qt::OpenHandCursor); + break; + default: + timeline_area->setCursor(Qt::ArrowCursor); + } } diff --git a/panels/timeline.h b/panels/timeline.h index 2cacaad7d..ac7d2033c 100644 --- a/panels/timeline.h +++ b/panels/timeline.h @@ -21,6 +21,11 @@ #ifndef TIMELINE_H #define TIMELINE_H +#include +#include +#include + +#include "ui/timelinewidget.h" #include "ui/timelinetools.h" #include "project/selection.h" #include "project/clip.h" @@ -28,12 +33,7 @@ #include "ui/timelineheader.h" #include "ui/resizablescrollbar.h" #include "ui/audiomonitor.h" -#include "ui/timelinewidget.h" - -#include -#include -#include -#include +#include "ui/panel.h" #define TRACK_DEFAULT_HEIGHT 40 @@ -52,236 +52,239 @@ void move_clip(ComboAction *ca, ClipPtr c, long iin, long iout, long iclip_in, i void ripple_clips(ComboAction *ca, SequencePtr s, long point, long length, const QVector& ignore = QVector()); struct Ghost { - int clip; - long in; - long out; - int track; - long clip_in; + int clip; + long in; + long out; + int track; + long clip_in; - long old_in; - long old_out; - int old_track; - long old_clip_in; + long old_in; + long old_out; + int old_track; + long old_clip_in; - // importing variables - Media* media; - int media_stream; + // importing variables + Media* media; + int media_stream; - // other variables - long ghost_length; - long media_length; - bool trim_in; - bool trimming; + // other variables + long ghost_length; + long media_length; + bool trim_in; + bool trimming; - // transition trimming - TransitionPtr transition; + // transition trimming + TransitionPtr transition; }; -class Timeline : public QDockWidget +class Timeline : public Panel { - Q_OBJECT + Q_OBJECT public: - explicit Timeline(QWidget *parent = nullptr); - ~Timeline(); + explicit Timeline(QWidget *parent = nullptr); + ~Timeline(); - bool focused(); - void multiply_zoom(double m); - void copy(bool del); - ClipPtr split_clip(ComboAction* ca, bool transitions, int p, long frame); - ClipPtr split_clip(ComboAction* ca, bool transitions, int p, long frame, long post_in); - bool split_selection(ComboAction* ca); - bool split_all_clips_at_point(ComboAction *ca, long point); - bool split_clip_and_relink(ComboAction* ca, int clip, long frame, bool relink); - void clean_up_selections(QVector& areas); - void deselect_area(long in, long out, int track); - void delete_areas_and_relink(ComboAction *ca, QVector& areas, bool deselect_areas); - void relink_clips_using_ids(QVector& old_clips, QVector& new_clips); - void update_sequence(); + bool focused(); + void multiply_zoom(double m); + void copy(bool del); + ClipPtr split_clip(ComboAction* ca, bool transitions, int p, long frame); + ClipPtr split_clip(ComboAction* ca, bool transitions, int p, long frame, long post_in); + bool split_selection(ComboAction* ca); + bool split_all_clips_at_point(ComboAction *ca, long point); + bool split_clip_and_relink(ComboAction* ca, int clip, long frame, bool relink); + void clean_up_selections(QVector& areas); + void deselect_area(long in, long out, int track); + void delete_areas_and_relink(ComboAction *ca, QVector& areas, bool deselect_areas); + 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); + 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); - void create_ghosts_from_media(SequencePtr seq, long entry_point, QVector &media_list); - void add_clips_from_ghosts(ComboAction *ca, SequencePtr s); + void create_ghosts_from_media(SequencePtr seq, long entry_point, QVector &media_list); + void add_clips_from_ghosts(ComboAction *ca, SequencePtr s); - int getTimelineScreenPointFromFrame(long frame); - long getTimelineFrameFromScreenPoint(int x); - int getDisplayScreenPointFromFrame(long frame); - long getDisplayFrameFromScreenPoint(int x); + int getTimelineScreenPointFromFrame(long frame); + long getTimelineFrameFromScreenPoint(int x); + int getDisplayScreenPointFromFrame(long frame); + long getDisplayFrameFromScreenPoint(int x); - int get_snap_range(); - bool snap_to_point(long point, long* l); - bool snap_to_timeline(long* l, bool use_playhead, bool use_markers, bool use_workarea); - void set_marker(); + int get_snap_range(); + bool snap_to_point(long point, long* l); + bool snap_to_timeline(long* l, bool use_playhead, bool use_markers, bool use_workarea); + void set_marker(); - // shared information - int tool; - long cursor_frame; - int cursor_track; - double zoom; - bool zoom_just_changed; - long drag_frame_start; - int drag_track_start; - void update_effect_controls(); - bool showing_all; - double old_zoom; + // shared information + int tool; + long cursor_frame; + int cursor_track; + double zoom; + bool zoom_just_changed; + long drag_frame_start; + int drag_track_start; + void update_effect_controls(); + 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); + QVector video_track_heights; + QVector audio_track_heights; + int get_track_height_size(bool video); + int calculate_track_height(int track, int height); - // snapping - bool snapping; - bool snapped; - long snap_point; + // snapping + bool snapping; + bool snapped; + long snap_point; - // selecting functions - bool selecting; - int selection_offset; - void delete_selection(QVector &selections, bool ripple); - 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; + // selecting functions + bool selecting; + int selection_offset; + void delete_selection(QVector &selections, bool ripple); + 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; - // moving - bool moving_init; - bool moving_proc; - QVector ghosts; - bool video_ghosts; - bool audio_ghosts; - bool move_insert; + // moving + bool moving_init; + bool moving_proc; + QVector ghosts; + bool video_ghosts; + bool audio_ghosts; + bool move_insert; - // trimming - int trim_target; - bool trim_in_point; - int transition_select; + // trimming + int trim_target; + bool trim_in_point; + int transition_select; - // splitting - bool splitting; - QVector split_tracks; - QVector split_cache; + // splitting + bool splitting; + QVector split_tracks; + QVector split_cache; - // importing - bool importing; - bool importing_files; + // importing + bool importing; + bool importing_files; - // creating variables - bool creating; - int creating_object; + // creating variables + bool creating; + int creating_object; - // transition variables - bool transition_tool_init; - bool transition_tool_proc; - int transition_tool_pre_clip; - int transition_tool_post_clip; - int transition_tool_type; - const EffectMeta* transition_tool_meta; - int transition_tool_side; + // transition variables + bool transition_tool_init; + bool transition_tool_proc; + int transition_tool_pre_clip; + int transition_tool_post_clip; + int transition_tool_type; + const EffectMeta* transition_tool_meta; + int transition_tool_side; - // hand tool variables - bool hand_moving; - int drag_x_start; - int drag_y_start; + // hand tool variables + bool hand_moving; + int drag_x_start; + int drag_y_start; - bool block_repaints; + bool block_repaints; - TimelineHeader* headers; - AudioMonitor* audio_monitor; - ResizableScrollBar* horizontalScrollBar; + TimelineHeader* headers; + AudioMonitor* audio_monitor; + ResizableScrollBar* horizontalScrollBar; - QPushButton* toolArrowButton; - QPushButton* toolEditButton; - QPushButton* toolRippleButton; - QPushButton* toolRazorButton; - QPushButton* toolSlipButton; - QPushButton* toolSlideButton; - QPushButton* toolHandButton; - QPushButton* toolTransitionButton; - QPushButton* snappingButton; + QPushButton* toolArrowButton; + QPushButton* toolEditButton; + QPushButton* toolRippleButton; + QPushButton* toolRazorButton; + QPushButton* toolSlipButton; + QPushButton* toolSlideButton; + QPushButton* toolHandButton; + QPushButton* toolTransitionButton; + QPushButton* snappingButton; - void scroll_to_frame(long frame); - void select_from_playhead(); + void scroll_to_frame(long frame); + void select_from_playhead(); - bool can_ripple_empty_space(long frame, int track); + bool can_ripple_empty_space(long frame, int track); - void resizeEvent(QResizeEvent *event); + void resizeEvent(QResizeEvent *event); +protected: + virtual void Retranslate() override; public slots: - void paste(bool insert = false); - void repaint_timeline(); - void toggle_show_all(); - void deselect(); - void toggle_links(); - void split_at_playhead(); - void ripple_delete(); - void ripple_delete_empty_space(); - void toggle_enable_on_selected_clips(); + void paste(bool insert = false); + void repaint_timeline(); + void toggle_show_all(); + void deselect(); + void toggle_links(); + void split_at_playhead(); + void ripple_delete(); + void ripple_delete_empty_space(); + void toggle_enable_on_selected_clips(); - void delete_inout(); - void ripple_delete_inout(); + void delete_inout(); + void ripple_delete_inout(); - void ripple_to_in_point(); - void ripple_to_out_point(); - void edit_to_in_point(); - void edit_to_out_point(); + void ripple_to_in_point(); + void ripple_to_out_point(); + void edit_to_in_point(); + void edit_to_out_point(); - void increase_track_height(); - void decrease_track_height(); + void increase_track_height(); + void decrease_track_height(); - void previous_cut(); - void next_cut(); + void previous_cut(); + void next_cut(); - void add_transition(); + void add_transition(); - void nest(); + void nest(); - void zoom_in(); - void zoom_out(); + void zoom_in(); + void zoom_out(); private slots: - void snapping_clicked(bool checked); - void add_btn_click(); - void add_menu_item(QAction*); - void setScroll(int); - void record_btn_click(); - void transition_tool_click(); - void transition_menu_select(QAction*); - void resize_move(double d); - void set_tool(); + void snapping_clicked(bool checked); + void add_btn_click(); + void add_menu_item(QAction*); + void setScroll(int); + void record_btn_click(); + void transition_tool_click(); + void transition_menu_select(QAction*); + void resize_move(double d); + void set_tool(); private: - void set_zoom_value(double v); - QVector tool_buttons; - void decheck_tool_buttons(QObject* sender); - void set_tool(int tool); - int scroll; - void set_sb_max(); + void set_zoom_value(double v); + QVector tool_buttons; + void decheck_tool_buttons(QObject* sender); + void set_tool(int tool); + int scroll; + void set_sb_max(); + void UpdateTitle(); - void setup_ui(); + void setup_ui(); - int default_track_height; + int default_track_height; - // ripple delete empty space variables - long rc_ripple_min; - long rc_ripple_max; + // ripple delete empty space variables + long rc_ripple_min; + long rc_ripple_max; - QWidget* timeline_area; - TimelineWidget* video_area; - TimelineWidget* audio_area; - QWidget* editAreas; - QScrollBar* videoScrollbar; - QScrollBar* audioScrollbar; - QPushButton* zoomInButton; - QPushButton* zoomOutButton; - QPushButton* recordButton; - QPushButton* addButton; - QWidget* tool_button_widget; + QWidget* timeline_area; + TimelineWidget* video_area; + TimelineWidget* audio_area; + QWidget* editAreas; + QScrollBar* videoScrollbar; + QScrollBar* audioScrollbar; + QPushButton* zoomInButton; + QPushButton* zoomOutButton; + QPushButton* recordButton; + QPushButton* addButton; + QWidget* tool_button_widget; }; #endif // TIMELINE_H diff --git a/panels/viewer.cpp b/panels/viewer.cpp index 037a3b735..927277f6c 100644 --- a/panels/viewer.cpp +++ b/panels/viewer.cpp @@ -56,7 +56,7 @@ extern "C" { #include Viewer::Viewer(QWidget *parent) : - QDockWidget(parent), + Panel(parent), playing(false), just_played(false), media(nullptr), @@ -99,6 +99,10 @@ Viewer::Viewer(QWidget *parent) : Viewer::~Viewer() {} +void Viewer::Retranslate() { + update_window_title(); +} + bool Viewer::is_focused() { return headers->hasFocus() || viewer_widget->hasFocus() diff --git a/panels/viewer.h b/panels/viewer.h index c69791199..f27a2cb24 100644 --- a/panels/viewer.h +++ b/panels/viewer.h @@ -21,7 +21,6 @@ #ifndef VIEWER_H #define VIEWER_H -#include #include #include #include @@ -30,6 +29,7 @@ #include "project/marker.h" #include "project/media.h" +#include "ui/panel.h" #include "ui/viewerwidget.h" #include "ui/timelinewidget.h" #include "ui/timelineheader.h" @@ -40,123 +40,127 @@ bool frame_rate_is_droppable(float rate); long timecode_to_frame(const QString& s, int view, double frame_rate); QString frame_to_timecode(long f, int view, double frame_rate); -class Viewer : public QDockWidget +class Viewer : public Panel { - Q_OBJECT + Q_OBJECT public: - explicit Viewer(QWidget *parent = nullptr); - ~Viewer(); + explicit Viewer(QWidget *parent = nullptr); + ~Viewer(); - bool is_focused(); - bool is_main_sequence(); - void set_main_sequence(); - void set_media(Media *m); - void compose(); - void set_playpause_icon(bool play); - void update_playhead_timecode(long p); - void update_end_timecode(); - void update_header_zoom(); - void clear_in(); - void clear_out(); - void clear_inout_point(); - void set_in_point(); - void set_out_point(); - void set_zoom(bool in); - void set_panel_name(const QString& n); + bool is_focused(); + bool is_main_sequence(); + void set_main_sequence(); + void set_media(Media *m); + void compose(); + void set_playpause_icon(bool play); + void update_playhead_timecode(long p); + void update_end_timecode(); + void update_header_zoom(); + void clear_in(); + void clear_out(); + void clear_inout_point(); + void set_in_point(); + void set_out_point(); + void set_zoom(bool in); + void set_panel_name(const QString& n); - // playback functions - void seek(long p); - void play(bool in_to_out = false); - void pause(); - bool playing; - long playhead_start; - qint64 start_msecs; - QTimer playback_updater; - bool just_played; + // playback functions + void seek(long p); + void play(bool in_to_out = false); + void pause(); + bool playing; + long playhead_start; + qint64 start_msecs; + QTimer playback_updater; + bool just_played; - void cue_recording(long start, long end, int track); - void uncue_recording(); - bool is_recording_cued(); - long recording_start; - long recording_end; - int recording_track; + void cue_recording(long start, long end, int track); + void uncue_recording(); + bool is_recording_cued(); + long recording_start; + long recording_end; + int recording_track; - void reset_all_audio(); - void update_parents(bool reload_fx = false); + void reset_all_audio(); + void update_parents(bool reload_fx = false); - int get_playback_speed(); + int get_playback_speed(); - ViewerWidget* viewer_widget; + ViewerWidget* viewer_widget; - Media* media; - SequencePtr seq; - QVector* marker_ref; + Media* media; + SequencePtr seq; + QVector* marker_ref; - void set_marker(); + void set_marker(); - TimelineHeader* headers; + TimelineHeader* headers; - void resizeEvent(QResizeEvent *event); + void resizeEvent(QResizeEvent *event); + +protected: + virtual void Retranslate() override; public slots: - void play_wake(); - void go_to_start(); - void go_to_in(); - void previous_frame(); - void toggle_play(); - void increase_speed(); - void decrease_speed(); - void next_frame(); - void go_to_out(); - void go_to_end(); - void close_media(); - void update_viewer(); + void play_wake(); + void go_to_start(); + void go_to_in(); + void previous_frame(); + void toggle_play(); + void increase_speed(); + void decrease_speed(); + void next_frame(); + void go_to_out(); + void go_to_end(); + void close_media(); + void update_viewer(); private slots: - void update_playhead(); - void timer_update(); - void recording_flasher_update(); - void resize_move(double d); + void update_playhead(); + void timer_update(); + void recording_flasher_update(); + void resize_move(double d); private: - void update_window_title(); - void clean_created_seq(); - void set_sequence(bool main, SequencePtr s); - bool main_sequence; - bool created_sequence; - long cached_end_frame; - QString panel_name; - double minimum_zoom; - bool playing_in_to_out; - long last_playhead; - void set_zoom_value(double d); - void set_sb_max(); - void set_playback_speed(int s); - long get_seq_in(); - long get_seq_out(); + void update_window_title(); + void clean_created_seq(); + void set_sequence(bool main, SequencePtr s); + bool main_sequence; + bool created_sequence; + long cached_end_frame; + QString panel_name; + double minimum_zoom; + bool playing_in_to_out; + long last_playhead; + void set_zoom_value(double d); + void set_sb_max(); + void set_playback_speed(int s); - QIcon playIcon; + long get_seq_in(); + long get_seq_out(); - void setup_ui(); + QIcon playIcon; - ResizableScrollBar* horizontal_bar; - ViewerContainer* viewer_container; - LabelSlider* current_timecode_slider; - QLabel* end_timecode; + void setup_ui(); - QPushButton* go_to_start_button; - QPushButton* prev_frame_button; - QPushButton* play_button; - QPushButton* next_frame_button; - QPushButton* go_to_end_frame; + ResizableScrollBar* horizontal_bar; + ViewerContainer* viewer_container; + LabelSlider* current_timecode_slider; + QLabel* end_timecode; - bool cue_recording_internal; - QTimer recording_flasher; + QPushButton* go_to_start_button; + QPushButton* prev_frame_button; + QPushButton* play_button; + QPushButton* next_frame_button; + QPushButton* go_to_end_frame; - long previous_playhead; - int playback_speed; + bool cue_recording_internal; + QTimer recording_flasher; + + long previous_playhead; + int playback_speed; }; #endif // VIEWER_H diff --git a/ui/panel.cpp b/ui/panel.cpp new file mode 100644 index 000000000..fd40ba786 --- /dev/null +++ b/ui/panel.cpp @@ -0,0 +1,35 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2019 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#include "panel.h" + +#include + +Panel::Panel(QWidget *parent) : QDockWidget (parent) { + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); +} + +bool Panel::event(QEvent *e) { + if (e->type() == QEvent::LanguageChange) { + Retranslate(); + return true; + } + return QDockWidget::event(e); +} diff --git a/ui/panel.h b/ui/panel.h new file mode 100644 index 000000000..920279432 --- /dev/null +++ b/ui/panel.h @@ -0,0 +1,35 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2019 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#ifndef PANEL_H +#define PANEL_H + +#include + +class Panel : public QDockWidget { + Q_OBJECT +public: + Panel(QWidget* parent = nullptr); + virtual bool event(QEvent* e) override; +protected: + virtual void Retranslate() = 0; +}; + +#endif // PANEL_H diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index bf3a48987..3a2acec10 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -64,305 +64,305 @@ #define TRANSITION_BETWEEN_RANGE 40 TimelineWidget::TimelineWidget(QWidget *parent) : QWidget(parent) { - selection_command = nullptr; - self_created_sequence = nullptr; - scroll = 0; + selection_command = nullptr; + self_created_sequence = nullptr; + scroll = 0; - bottom_align = false; - track_resizing = false; - setMouseTracking(true); + bottom_align = false; + track_resizing = false; + setMouseTracking(true); - setAcceptDrops(true); + setAcceptDrops(true); - setContextMenuPolicy(Qt::CustomContextMenu); - connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu(const QPoint&))); + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu(const QPoint&))); - tooltip_timer.setInterval(500); - connect(&tooltip_timer, SIGNAL(timeout()), this, SLOT(tooltip_timer_timeout())); + tooltip_timer.setInterval(500); + connect(&tooltip_timer, SIGNAL(timeout()), this, SLOT(tooltip_timer_timeout())); } void TimelineWidget::show_context_menu(const QPoint& pos) { - if (olive::ActiveSequence != nullptr) { - // hack because sometimes right clicking doesn't trigger mouse release event - panel_timeline->rect_select_init = false; - panel_timeline->rect_select_proc = false; + if (olive::ActiveSequence != nullptr) { + // hack because sometimes right clicking doesn't trigger mouse release event + panel_timeline->rect_select_init = false; + panel_timeline->rect_select_proc = false; - QMenu menu(this); + QMenu menu(this); - // TODO replace with Olive::MenuHelper::make_edit_functions_menu() without losing functionality + // TODO replace with Olive::MenuHelper::make_edit_functions_menu() without losing functionality - QAction* undoAction = menu.addAction(tr("&Undo")); - QAction* redoAction = menu.addAction(tr("&Redo")); - connect(undoAction, SIGNAL(triggered(bool)), olive::Global.get(), SLOT(undo())); - connect(redoAction, SIGNAL(triggered(bool)), olive::Global.get(), SLOT(redo())); - undoAction->setEnabled(olive::UndoStack.canUndo()); - redoAction->setEnabled(olive::UndoStack.canRedo()); - menu.addSeparator(); + QAction* undoAction = menu.addAction(tr("&Undo")); + QAction* redoAction = menu.addAction(tr("&Redo")); + connect(undoAction, SIGNAL(triggered(bool)), olive::Global.get(), SLOT(undo())); + connect(redoAction, SIGNAL(triggered(bool)), olive::Global.get(), SLOT(redo())); + undoAction->setEnabled(olive::UndoStack.canUndo()); + redoAction->setEnabled(olive::UndoStack.canRedo()); + menu.addSeparator(); - // collect all the selected clips - QVector selected_clips; - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr && is_clip_selected(c, true)) { - selected_clips.append(c); - } - } + // collect all the selected clips + QVector selected_clips; + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr && is_clip_selected(c, true)) { + selected_clips.append(c); + } + } - if (!selected_clips.isEmpty()) { - // clips are selected - menu.addAction(tr("C&ut"), &olive::FocusFilter, SLOT(cut())); - menu.addAction(tr("Cop&y"), &olive::FocusFilter, SLOT(copy())); - } + if (!selected_clips.isEmpty()) { + // clips are selected + menu.addAction(tr("C&ut"), &olive::FocusFilter, SLOT(cut())); + menu.addAction(tr("Cop&y"), &olive::FocusFilter, SLOT(copy())); + } - menu.addAction(tr("&Paste"), olive::Global.get(), SLOT(paste())); + menu.addAction(tr("&Paste"), olive::Global.get(), SLOT(paste())); - if (selected_clips.isEmpty()) { - // no clips are selected + if (selected_clips.isEmpty()) { + // no clips are selected - // determine if we can perform a ripple empty space - panel_timeline->cursor_frame = panel_timeline->getTimelineFrameFromScreenPoint(pos.x()); - panel_timeline->cursor_track = getTrackFromScreenPoint(pos.y()); + // determine if we can perform a ripple empty space + panel_timeline->cursor_frame = panel_timeline->getTimelineFrameFromScreenPoint(pos.x()); + panel_timeline->cursor_track = getTrackFromScreenPoint(pos.y()); - if (panel_timeline->can_ripple_empty_space(panel_timeline->cursor_frame, panel_timeline->cursor_track)) { - QAction* ripple_delete_action = menu.addAction(tr("R&ipple Delete")); - connect(ripple_delete_action, SIGNAL(triggered(bool)), panel_timeline, SLOT(ripple_delete_empty_space())); - } + if (panel_timeline->can_ripple_empty_space(panel_timeline->cursor_frame, panel_timeline->cursor_track)) { + QAction* ripple_delete_action = menu.addAction(tr("R&ipple Delete")); + connect(ripple_delete_action, SIGNAL(triggered(bool)), panel_timeline, SLOT(ripple_delete_empty_space())); + } - QAction* seq_settings = menu.addAction(tr("Sequence Settings")); - connect(seq_settings, SIGNAL(triggered(bool)), this, SLOT(open_sequence_properties())); - } + QAction* seq_settings = menu.addAction(tr("Sequence Settings")); + connect(seq_settings, SIGNAL(triggered(bool)), this, SLOT(open_sequence_properties())); + } - if (!selected_clips.isEmpty()) { - menu.addSeparator(); - menu.addAction(tr("&Speed/Duration"), olive::Global.get(), SLOT(open_speed_dialog())); + if (!selected_clips.isEmpty()) { + menu.addSeparator(); + menu.addAction(tr("&Speed/Duration"), olive::Global.get(), SLOT(open_speed_dialog())); - QAction* autoscaleAction = menu.addAction(tr("Auto-s&cale"), this, SLOT(toggle_autoscale())); - autoscaleAction->setCheckable(true); - // set autoscale to the first selected clip - autoscaleAction->setChecked(selected_clips.at(0)->autoscale); + QAction* autoscaleAction = menu.addAction(tr("Auto-s&cale"), this, SLOT(toggle_autoscale())); + autoscaleAction->setCheckable(true); + // set autoscale to the first selected clip + autoscaleAction->setChecked(selected_clips.at(0)->autoscale); - olive::MenuHelper.make_clip_functions_menu(&menu); + olive::MenuHelper.make_clip_functions_menu(&menu); - // stabilizer option - /*int video_clip_count = 0; - bool all_video_is_footage = true; - for (int i=0;itrack < 0) { - video_clip_count++; - if (selected_clips.at(i)->media == nullptr - || selected_clips.at(i)->media->get_type() != MEDIA_TYPE_FOOTAGE) { - all_video_is_footage = false; - } - } - } - if (video_clip_count == 1 && all_video_is_footage) { - QAction* stabilizerAction = menu.addAction("S&tabilizer"); - connect(stabilizerAction, SIGNAL(triggered(bool)), this, SLOT(show_stabilizer_diag())); - }*/ + // stabilizer option + /*int video_clip_count = 0; + bool all_video_is_footage = true; + for (int i=0;itrack < 0) { + video_clip_count++; + if (selected_clips.at(i)->media == nullptr + || selected_clips.at(i)->media->get_type() != MEDIA_TYPE_FOOTAGE) { + all_video_is_footage = false; + } + } + } + if (video_clip_count == 1 && all_video_is_footage) { + QAction* stabilizerAction = menu.addAction("S&tabilizer"); + connect(stabilizerAction, SIGNAL(triggered(bool)), this, SLOT(show_stabilizer_diag())); + }*/ - // check if all selected clips have the same media for a "Reveal In Project" - bool same_media = true; - rc_reveal_media = selected_clips.at(0)->media; - for (int i=1;imedia != rc_reveal_media) { - same_media = false; - break; - } - } + // check if all selected clips have the same media for a "Reveal In Project" + bool same_media = true; + rc_reveal_media = selected_clips.at(0)->media; + for (int i=1;imedia != rc_reveal_media) { + same_media = false; + break; + } + } - if (same_media) { - QAction* revealInProjectAction = menu.addAction(tr("&Reveal in Project")); - connect(revealInProjectAction, SIGNAL(triggered(bool)), this, SLOT(reveal_media())); - } + if (same_media) { + QAction* revealInProjectAction = menu.addAction(tr("&Reveal in Project")); + connect(revealInProjectAction, SIGNAL(triggered(bool)), this, SLOT(reveal_media())); + } - QAction* rename = menu.addAction(tr("R&ename")); - connect(rename, SIGNAL(triggered(bool)), this, SLOT(rename_clip())); - } + QAction* rename = menu.addAction(tr("R&ename")); + connect(rename, SIGNAL(triggered(bool)), this, SLOT(rename_clip())); + } - menu.exec(mapToGlobal(pos)); - } + menu.exec(mapToGlobal(pos)); + } } void TimelineWidget::toggle_autoscale() { - SetAutoscaleAction* action = new SetAutoscaleAction(); - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr && is_clip_selected(c, true)) { - action->clips.append(c); - } - } - if (action->clips.size() > 0) { - olive::UndoStack.push(action); - } else { - delete action; - } + SetAutoscaleAction* action = new SetAutoscaleAction(); + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr && is_clip_selected(c, true)) { + action->clips.append(c); + } + } + if (action->clips.size() > 0) { + olive::UndoStack.push(action); + } else { + delete action; + } } void TimelineWidget::tooltip_timer_timeout() { - if (olive::ActiveSequence != nullptr) { - if (tooltip_clip < olive::ActiveSequence->clips.size()) { - ClipPtr c = olive::ActiveSequence->clips.at(tooltip_clip); - if (c != nullptr) { - QToolTip::showText(QCursor::pos(), - tr("%1\nStart: %2\nEnd: %3\nDuration: %4").arg( - c->name, - frame_to_timecode(c->timeline_in, olive::CurrentConfig.timecode_view, olive::ActiveSequence->frame_rate), - frame_to_timecode(c->timeline_out, olive::CurrentConfig.timecode_view, olive::ActiveSequence->frame_rate), - frame_to_timecode(c->getLength(), olive::CurrentConfig.timecode_view, olive::ActiveSequence->frame_rate) - )); - } - } - } - tooltip_timer.stop(); + if (olive::ActiveSequence != nullptr) { + if (tooltip_clip < olive::ActiveSequence->clips.size()) { + ClipPtr c = olive::ActiveSequence->clips.at(tooltip_clip); + if (c != nullptr) { + QToolTip::showText(QCursor::pos(), + tr("%1\nStart: %2\nEnd: %3\nDuration: %4").arg( + c->name, + frame_to_timecode(c->timeline_in, olive::CurrentConfig.timecode_view, olive::ActiveSequence->frame_rate), + frame_to_timecode(c->timeline_out, olive::CurrentConfig.timecode_view, olive::ActiveSequence->frame_rate), + frame_to_timecode(c->getLength(), olive::CurrentConfig.timecode_view, olive::ActiveSequence->frame_rate) + )); + } + } + } + tooltip_timer.stop(); } void TimelineWidget::rename_clip() { - QVector selected_clips; - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr && is_clip_selected(c, true)) { - selected_clips.append(c); - } - } - if (selected_clips.size() > 0) { - QString s = QInputDialog::getText(this, - (selected_clips.size() == 1) ? tr("Rename '%1'").arg(selected_clips.at(0)->name) : tr("Rename multiple clips"), - tr("Enter a new name for this clip:"), - QLineEdit::Normal, - selected_clips.at(0)->name - ); - if (!s.isEmpty()) { - RenameClipCommand* rcc = new RenameClipCommand(); - rcc->new_name = s; - rcc->clips = selected_clips; - olive::UndoStack.push(rcc); - update_ui(true); - } - } + QVector selected_clips; + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr && is_clip_selected(c, true)) { + selected_clips.append(c); + } + } + if (selected_clips.size() > 0) { + QString s = QInputDialog::getText(this, + (selected_clips.size() == 1) ? tr("Rename '%1'").arg(selected_clips.at(0)->name) : tr("Rename multiple clips"), + tr("Enter a new name for this clip:"), + QLineEdit::Normal, + selected_clips.at(0)->name + ); + if (!s.isEmpty()) { + RenameClipCommand* rcc = new RenameClipCommand(); + rcc->new_name = s; + rcc->clips = selected_clips; + olive::UndoStack.push(rcc); + update_ui(true); + } + } } void TimelineWidget::open_sequence_properties() { - QList sequence_items; - QList all_top_level_items; - for (int i=0;iget_all_media_from_table(all_top_level_items, sequence_items, MEDIA_TYPE_SEQUENCE); // find all sequences in project - for (int i=0;ito_sequence() == olive::ActiveSequence) { - NewSequenceDialog nsd(this, sequence_items.at(i)); - nsd.exec(); - return; - } - } - QMessageBox::critical(this, tr("Error"), tr("Couldn't locate media wrapper for sequence.")); + QList sequence_items; + QList all_top_level_items; + for (int i=0;iget_all_media_from_table(all_top_level_items, sequence_items, MEDIA_TYPE_SEQUENCE); // find all sequences in project + for (int i=0;ito_sequence() == olive::ActiveSequence) { + NewSequenceDialog nsd(this, sequence_items.at(i)); + nsd.exec(); + return; + } + } + QMessageBox::critical(this, tr("Error"), tr("Couldn't locate media wrapper for sequence.")); } bool same_sign(int a, int b) { - return (a < 0) == (b < 0); + return (a < 0) == (b < 0); } void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { - bool import_init = false; + bool import_init = false; - QVector media_list; - panel_timeline->importing_files = false; + QVector media_list; + panel_timeline->importing_files = false; - if (event->source() == panel_project->tree_view || event->source() == panel_project->icon_view) { - QModelIndexList items = panel_project->get_current_selected(); - media_list.resize(items.size()); - for (int i=0;iitem_to_media(items.at(i)); - } - import_init = true; - } + if (event->source() == panel_project->tree_view || event->source() == panel_project->icon_view) { + QModelIndexList items = panel_project->get_current_selected(); + media_list.resize(items.size()); + for (int i=0;iitem_to_media(items.at(i)); + } + import_init = true; + } - if (event->source() == panel_footage_viewer->viewer_widget) { - SequencePtr proposed_seq = panel_footage_viewer->seq; - if (proposed_seq != olive::ActiveSequence) { // don't allow nesting the same sequence - media_list.append(panel_footage_viewer->media); - import_init = true; - } - } + if (event->source() == panel_footage_viewer->viewer_widget) { + SequencePtr proposed_seq = panel_footage_viewer->seq; + if (proposed_seq != olive::ActiveSequence) { // don't allow nesting the same sequence + media_list.append(panel_footage_viewer->media); + import_init = true; + } + } - if (olive::CurrentConfig.enable_drag_files_to_timeline && event->mimeData()->hasUrls()) { - QList urls = event->mimeData()->urls(); - if (!urls.isEmpty()) { - QStringList file_list; + if (olive::CurrentConfig.enable_drag_files_to_timeline && event->mimeData()->hasUrls()) { + QList urls = event->mimeData()->urls(); + if (!urls.isEmpty()) { + QStringList file_list; - for (int i=0;iprocess_file_list(file_list); + panel_project->process_file_list(file_list); - for (int i=0;ilast_imported_media.size();i++) { - // waits for media to have a duration - // TODO would be much nicer if this was multithreaded - FootagePtr f = panel_project->last_imported_media.at(i)->to_footage(); - f->ready_lock.lock(); - f->ready_lock.unlock(); + for (int i=0;ilast_imported_media.size();i++) { + // waits for media to have a duration + // TODO would be much nicer if this was multithreaded + FootagePtr f = panel_project->last_imported_media.at(i)->to_footage(); + f->ready_lock.lock(); + f->ready_lock.unlock(); - if (f->ready) { - media_list.append(panel_project->last_imported_media.at(i)); - } - } + if (f->ready) { + media_list.append(panel_project->last_imported_media.at(i)); + } + } - if (media_list.isEmpty()) { - olive::UndoStack.undo(); - } else { - import_init = true; - panel_timeline->importing_files = true; - } - } - } + if (media_list.isEmpty()) { + olive::UndoStack.undo(); + } else { + import_init = true; + panel_timeline->importing_files = true; + } + } + } - if (import_init) { - event->acceptProposedAction(); + if (import_init) { + event->acceptProposedAction(); - long entry_point; - SequencePtr seq = olive::ActiveSequence; + long entry_point; + SequencePtr seq = olive::ActiveSequence; - if (seq == nullptr) { - // if no sequence, we're going to create a new one using the clips as a reference - entry_point = 0; + if (seq == nullptr) { + // if no sequence, we're going to create a new one using the clips as a reference + entry_point = 0; - self_created_sequence = create_sequence_from_media(media_list); - seq = self_created_sequence; - } else { - entry_point = panel_timeline->getTimelineFrameFromScreenPoint(event->pos().x()); - panel_timeline->drag_frame_start = entry_point + getFrameFromScreenPoint(panel_timeline->zoom, 50); - panel_timeline->drag_track_start = (bottom_align) ? -1 : 0; - } + self_created_sequence = create_sequence_from_media(media_list); + seq = self_created_sequence; + } else { + entry_point = panel_timeline->getTimelineFrameFromScreenPoint(event->pos().x()); + panel_timeline->drag_frame_start = entry_point + getFrameFromScreenPoint(panel_timeline->zoom, 50); + panel_timeline->drag_track_start = (bottom_align) ? -1 : 0; + } - panel_timeline->create_ghosts_from_media(seq, entry_point, media_list); + panel_timeline->create_ghosts_from_media(seq, entry_point, media_list); - panel_timeline->importing = true; - } + panel_timeline->importing = true; + } } void TimelineWidget::dragMoveEvent(QDragMoveEvent *event) { - if (panel_timeline->importing) { - event->acceptProposedAction(); + if (panel_timeline->importing) { + event->acceptProposedAction(); - if (olive::ActiveSequence != nullptr) { - QPoint pos = event->pos(); - update_ghosts(pos, event->keyboardModifiers() & Qt::ShiftModifier); - panel_timeline->move_insert = ((event->keyboardModifiers() & Qt::ControlModifier) && (panel_timeline->tool == TIMELINE_TOOL_POINTER || panel_timeline->importing)); - update_ui(false); - } - } + if (olive::ActiveSequence != nullptr) { + QPoint pos = event->pos(); + update_ghosts(pos, event->keyboardModifiers() & Qt::ShiftModifier); + panel_timeline->move_insert = ((event->keyboardModifiers() & Qt::ControlModifier) && (panel_timeline->tool == TIMELINE_TOOL_POINTER || panel_timeline->importing)); + update_ui(false); + } + } } void TimelineWidget::wheelEvent(QWheelEvent *event) { - // shift used to toggle zooming instead of scrolling - bool shift = (event->modifiers() & Qt::ShiftModifier); + // shift used to toggle zooming instead of scrolling + bool shift = (event->modifiers() & Qt::ShiftModifier); - // - // NOTE/FIXME: CURRENTLY disabling pixel scrolling because it needs more testing - // + // + // NOTE/FIXME: CURRENTLY disabling pixel scrolling because it needs more testing + // - /*if (!event->pixelDelta().isNull()) { + /*if (!event->pixelDelta().isNull()) { // if we got pixel scrolling data, prefer it over the angleDelta data QScrollBar* horiz_bar = panel_timeline->horizontalScrollBar; @@ -373,2453 +373,2453 @@ void TimelineWidget::wheelEvent(QWheelEvent *event) { } else*/ if (!event->angleDelta().isNull()) { - // alt is used to swap horizontal and vertical scrolling - bool alt = (event->modifiers() & Qt::AltModifier); + // alt is used to swap horizontal and vertical scrolling + bool alt = (event->modifiers() & Qt::AltModifier); - int scroll_amount = alt ? (event->angleDelta().x()) : (event->angleDelta().y()); + int scroll_amount = alt ? (event->angleDelta().x()) : (event->angleDelta().y()); - bool in = (scroll_amount > 0); - if (olive::CurrentConfig.scroll_zooms != shift) { + bool in = (scroll_amount > 0); + if (olive::CurrentConfig.scroll_zooms != shift) { - // if config.scroll_zooms is enabled or shift is held, zoom instead of scrolling - if (in) { - panel_timeline->multiply_zoom(1.5); - } else { - panel_timeline->multiply_zoom(0.75); - } + // if config.scroll_zooms is enabled or shift is held, zoom instead of scrolling + if (in) { + panel_timeline->multiply_zoom(1.5); + } else { + panel_timeline->multiply_zoom(0.75); + } - } else { - // pass the scrolling to the Timeline's main scrollbar for horizontal scrolling, or this widget's - // scrollbar for vertical scrolling + } else { + // pass the scrolling to the Timeline's main scrollbar for horizontal scrolling, or this widget's + // scrollbar for vertical scrolling - QScrollBar* bar = alt ? scrollBar : panel_timeline->horizontalScrollBar; + QScrollBar* bar = alt ? scrollBar : panel_timeline->horizontalScrollBar; - int step = bar->singleStep(); - if (in) step = -step; - bar->setValue(bar->value() + step); - } + int step = bar->singleStep(); + if (in) step = -step; + bar->setValue(bar->value() + step); } + } } void TimelineWidget::dragLeaveEvent(QDragLeaveEvent* event) { - event->accept(); - if (panel_timeline->importing) { - if (panel_timeline->importing_files) { - olive::UndoStack.undo(); - } - panel_timeline->importing_files = false; - panel_timeline->ghosts.clear(); - panel_timeline->importing = false; - update_ui(false); - } - if (self_created_sequence != nullptr) { - self_created_sequence.reset(); - self_created_sequence = nullptr; - } + event->accept(); + if (panel_timeline->importing) { + if (panel_timeline->importing_files) { + olive::UndoStack.undo(); + } + panel_timeline->importing_files = false; + panel_timeline->ghosts.clear(); + panel_timeline->importing = false; + update_ui(false); + } + if (self_created_sequence != nullptr) { + self_created_sequence.reset(); + self_created_sequence = nullptr; + } } void delete_area_under_ghosts(ComboAction* ca) { - // delete areas before adding - QVector delete_areas; - for (int i=0;ighosts.size();i++) { - const Ghost& g = panel_timeline->ghosts.at(i); - Selection sel; - sel.in = g.in; - sel.out = g.out; - sel.track = g.track; - delete_areas.append(sel); - } - panel_timeline->delete_areas_and_relink(ca, delete_areas, false); + // delete areas before adding + QVector delete_areas; + for (int i=0;ighosts.size();i++) { + const Ghost& g = panel_timeline->ghosts.at(i); + Selection sel; + sel.in = g.in; + sel.out = g.out; + sel.track = g.track; + delete_areas.append(sel); + } + panel_timeline->delete_areas_and_relink(ca, delete_areas, false); } void insert_clips(ComboAction* ca) { - bool ripple_old_point = true; + bool ripple_old_point = true; - long earliest_old_point = LONG_MAX; - long latest_old_point = LONG_MIN; + long earliest_old_point = LONG_MAX; + long latest_old_point = LONG_MIN; - long earliest_new_point = LONG_MAX; - long latest_new_point = LONG_MIN; + long earliest_new_point = LONG_MAX; + long latest_new_point = LONG_MIN; - QVector ignore_clips; - for (int i=0;ighosts.size();i++) { - const Ghost& g = panel_timeline->ghosts.at(i); + QVector ignore_clips; + for (int i=0;ighosts.size();i++) { + const Ghost& g = panel_timeline->ghosts.at(i); - earliest_old_point = qMin(earliest_old_point, g.old_in); - latest_old_point = qMax(latest_old_point, g.old_out); - earliest_new_point = qMin(earliest_new_point, g.in); - latest_new_point = qMax(latest_new_point, g.out); + earliest_old_point = qMin(earliest_old_point, g.old_in); + latest_old_point = qMax(latest_old_point, g.old_out); + earliest_new_point = qMin(earliest_new_point, g.in); + latest_new_point = qMax(latest_new_point, g.out); - if (g.clip >= 0) { - ignore_clips.append(g.clip); - } else { - // don't try to close old gap if importing - ripple_old_point = false; - } - } + if (g.clip >= 0) { + ignore_clips.append(g.clip); + } else { + // don't try to close old gap if importing + ripple_old_point = false; + } + } - panel_timeline->split_cache.clear(); + panel_timeline->split_cache.clear(); - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr) { - // don't split any clips that are moving - bool found = false; - for (int j=0;jghosts.size();j++) { - if (panel_timeline->ghosts.at(j).clip == i) { - found = true; - break; - } - } - if (!found) { - if (c->timeline_in < earliest_new_point && c->timeline_out > earliest_new_point) { - panel_timeline->split_clip_and_relink(ca, i, earliest_new_point, true); - } + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr) { + // don't split any clips that are moving + bool found = false; + for (int j=0;jghosts.size();j++) { + if (panel_timeline->ghosts.at(j).clip == i) { + found = true; + break; + } + } + if (!found) { + if (c->timeline_in < earliest_new_point && c->timeline_out > earliest_new_point) { + panel_timeline->split_clip_and_relink(ca, i, earliest_new_point, true); + } - // determine if we should close the gap the old clips left behind - if (ripple_old_point - && !((c->timeline_in < earliest_old_point && c->timeline_out <= earliest_old_point) || (c->timeline_in >= latest_old_point && c->timeline_out > latest_old_point)) - && !ignore_clips.contains(i)) { - ripple_old_point = false; - } - } - } - } + // determine if we should close the gap the old clips left behind + if (ripple_old_point + && !((c->timeline_in < earliest_old_point && c->timeline_out <= earliest_old_point) || (c->timeline_in >= latest_old_point && c->timeline_out > latest_old_point)) + && !ignore_clips.contains(i)) { + ripple_old_point = false; + } + } + } + } - long ripple_length = (latest_new_point - earliest_new_point); + long ripple_length = (latest_new_point - earliest_new_point); - ripple_clips(ca, olive::ActiveSequence, earliest_new_point, ripple_length, ignore_clips); + ripple_clips(ca, olive::ActiveSequence, earliest_new_point, ripple_length, ignore_clips); - if (ripple_old_point) { - // works for moving later clips earlier but not earlier to later - long second_ripple_length = (earliest_old_point - latest_old_point); + if (ripple_old_point) { + // works for moving later clips earlier but not earlier to later + long second_ripple_length = (earliest_old_point - latest_old_point); - ripple_clips(ca, olive::ActiveSequence, latest_old_point, second_ripple_length, ignore_clips); + ripple_clips(ca, olive::ActiveSequence, latest_old_point, second_ripple_length, ignore_clips); - if (earliest_old_point < earliest_new_point) { - for (int i=0;ighosts.size();i++) { - Ghost& g = panel_timeline->ghosts[i]; - g.in += second_ripple_length; - g.out += second_ripple_length; - } - for (int i=0;iselections.size();i++) { - Selection& s = olive::ActiveSequence->selections[i]; - s.in += second_ripple_length; - s.out += second_ripple_length; - } - } - } + if (earliest_old_point < earliest_new_point) { + for (int i=0;ighosts.size();i++) { + Ghost& g = panel_timeline->ghosts[i]; + g.in += second_ripple_length; + g.out += second_ripple_length; + } + for (int i=0;iselections.size();i++) { + Selection& s = olive::ActiveSequence->selections[i]; + s.in += second_ripple_length; + s.out += second_ripple_length; + } + } + } } void TimelineWidget::dropEvent(QDropEvent* event) { - if (panel_timeline->importing && panel_timeline->ghosts.size() > 0) { - event->acceptProposedAction(); + if (panel_timeline->importing && panel_timeline->ghosts.size() > 0) { + event->acceptProposedAction(); - ComboAction* ca = new ComboAction(); + ComboAction* ca = new ComboAction(); - SequencePtr s = olive::ActiveSequence; + SequencePtr s = olive::ActiveSequence; - // if we're dropping into nothing, create a new sequences based on the clip being dragged - if (s == nullptr) { - s = self_created_sequence; - panel_project->create_sequence_internal(ca, self_created_sequence, true, nullptr); - self_created_sequence = nullptr; - } else if (event->keyboardModifiers() & Qt::ControlModifier) { - insert_clips(ca); - } else { - delete_area_under_ghosts(ca); - } + // if we're dropping into nothing, create a new sequences based on the clip being dragged + if (s == nullptr) { + s = self_created_sequence; + panel_project->create_sequence_internal(ca, self_created_sequence, true, nullptr); + self_created_sequence = nullptr; + } else if (event->keyboardModifiers() & Qt::ControlModifier) { + insert_clips(ca); + } else { + delete_area_under_ghosts(ca); + } - panel_timeline->add_clips_from_ghosts(ca, s); + panel_timeline->add_clips_from_ghosts(ca, s); - olive::UndoStack.push(ca); + olive::UndoStack.push(ca); - setFocus(); + setFocus(); - update_ui(true); - } + update_ui(true); + } } void TimelineWidget::mouseDoubleClickEvent(QMouseEvent *event) { - if (olive::ActiveSequence != nullptr) { - if (panel_timeline->tool == TIMELINE_TOOL_EDIT) { - int clip_index = getClipIndexFromCoords(panel_timeline->cursor_frame, panel_timeline->cursor_track); - if (clip_index >= 0) { - ClipPtr clip = olive::ActiveSequence->clips.at(clip_index); - if (!(event->modifiers() & Qt::ShiftModifier)) olive::ActiveSequence->selections.clear(); - Selection s; - s.in = clip->timeline_in; - s.out = clip->timeline_out; - s.track = clip->track; - olive::ActiveSequence->selections.append(s); - update_ui(false); - } - } else if (panel_timeline->tool == TIMELINE_TOOL_POINTER) { - int clip_index = getClipIndexFromCoords(panel_timeline->cursor_frame, panel_timeline->cursor_track); - if (clip_index >= 0) { - ClipPtr c = olive::ActiveSequence->clips.at(clip_index); - if (c->media != nullptr && c->media->get_type() == MEDIA_TYPE_SEQUENCE) { - set_sequence(c->media->to_sequence()); - } - } + if (olive::ActiveSequence != nullptr) { + if (panel_timeline->tool == TIMELINE_TOOL_EDIT) { + int clip_index = getClipIndexFromCoords(panel_timeline->cursor_frame, panel_timeline->cursor_track); + if (clip_index >= 0) { + ClipPtr clip = olive::ActiveSequence->clips.at(clip_index); + if (!(event->modifiers() & Qt::ShiftModifier)) olive::ActiveSequence->selections.clear(); + Selection s; + s.in = clip->timeline_in; + s.out = clip->timeline_out; + s.track = clip->track; + olive::ActiveSequence->selections.append(s); + update_ui(false); + } + } else if (panel_timeline->tool == TIMELINE_TOOL_POINTER) { + int clip_index = getClipIndexFromCoords(panel_timeline->cursor_frame, panel_timeline->cursor_track); + if (clip_index >= 0) { + ClipPtr c = olive::ActiveSequence->clips.at(clip_index); + if (c->media != nullptr && c->media->get_type() == MEDIA_TYPE_SEQUENCE) { + set_sequence(c->media->to_sequence()); } + } } + } } bool isLiveEditing() { - return (panel_timeline->tool == TIMELINE_TOOL_EDIT || panel_timeline->tool == TIMELINE_TOOL_RAZOR || panel_timeline->creating); + 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; - if (event->button() == Qt::MiddleButton) { - tool = TIMELINE_TOOL_HAND; - panel_timeline->creating = false; - } else if (event->button() == Qt::RightButton) { - tool = TIMELINE_TOOL_MENU; - panel_timeline->creating = false; - } + if (olive::ActiveSequence != nullptr) { + int tool = panel_timeline->tool; + if (event->button() == Qt::MiddleButton) { + tool = TIMELINE_TOOL_HAND; + panel_timeline->creating = false; + } else if (event->button() == Qt::RightButton) { + 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()); - } + 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()); + } - int clip_index = panel_timeline->trim_target; - if (clip_index == -1) clip_index = getClipIndexFromCoords(panel_timeline->drag_frame_start, panel_timeline->drag_track_start); + int clip_index = panel_timeline->trim_target; + if (clip_index == -1) clip_index = getClipIndexFromCoords(panel_timeline->drag_frame_start, panel_timeline->drag_track_start); - bool shift = (event->modifiers() & Qt::ShiftModifier); - bool alt = (event->modifiers() & Qt::AltModifier); + bool shift = (event->modifiers() & Qt::ShiftModifier); + bool alt = (event->modifiers() & Qt::AltModifier); - if (shift) { - panel_timeline->selection_offset = olive::ActiveSequence->selections.size(); - } else { - panel_timeline->selection_offset = 0; - } + if (shift) { + panel_timeline->selection_offset = olive::ActiveSequence->selections.size(); + } else { + panel_timeline->selection_offset = 0; + } - if (panel_timeline->creating) { - int comp = 0; - switch (panel_timeline->creating_object) { - case ADD_OBJ_TITLE: - case ADD_OBJ_SOLID: - case ADD_OBJ_BARS: - comp = -1; - break; - case ADD_OBJ_TONE: - case ADD_OBJ_NOISE: - case ADD_OBJ_AUDIO: - comp = 1; - break; - } + if (panel_timeline->creating) { + int comp = 0; + switch (panel_timeline->creating_object) { + case ADD_OBJ_TITLE: + case ADD_OBJ_SOLID: + case ADD_OBJ_BARS: + comp = -1; + break; + case ADD_OBJ_TONE: + case ADD_OBJ_NOISE: + case ADD_OBJ_AUDIO: + comp = 1; + break; + } - 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; - panel_timeline->ghosts.append(g); + 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; + panel_timeline->ghosts.append(g); - panel_timeline->moving_init = true; - panel_timeline->moving_proc = true; - } - } else { - switch (tool) { - case TIMELINE_TOOL_POINTER: - case TIMELINE_TOOL_RIPPLE: - case TIMELINE_TOOL_SLIP: - case TIMELINE_TOOL_ROLLING: - case TIMELINE_TOOL_SLIDE: - case TIMELINE_TOOL_MENU: - { - if (track_resizing && tool != TIMELINE_TOOL_MENU) { - track_resize_mouse_cache = event->pos().y(); - 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); + panel_timeline->moving_init = true; + panel_timeline->moving_proc = true; + } + } else { + switch (tool) { + case TIMELINE_TOOL_POINTER: + case TIMELINE_TOOL_RIPPLE: + case TIMELINE_TOOL_SLIP: + case TIMELINE_TOOL_ROLLING: + case TIMELINE_TOOL_SLIDE: + case TIMELINE_TOOL_MENU: + { + if (track_resizing && tool != TIMELINE_TOOL_MENU) { + track_resize_mouse_cache = event->pos().y(); + 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); + 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); - 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); - } + 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; + 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(); - } + 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(); + } - Selection s; + Selection s; - s.in = clip->timeline_in; - s.out = clip->timeline_out; + 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->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(); - } - } + 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); + s.track = clip->track; + olive::ActiveSequence->selections.append(s); - if (olive::CurrentConfig.select_also_seeks) { - panel_sequence_viewer->seek(clip->timeline_in); - } + if (olive::CurrentConfig.select_also_seeks) { + panel_sequence_viewer->seek(clip->timeline_in); + } - // 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 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 (tool != TIMELINE_TOOL_MENU) panel_timeline->moving_init = true; - } else { - // if "shift" is not down - if (!shift) { - olive::ActiveSequence->selections.clear(); - } + if (tool != TIMELINE_TOOL_MENU) panel_timeline->moving_init = true; + } else { + // if "shift" is not down + if (!shift) { + olive::ActiveSequence->selections.clear(); + } - panel_timeline->rect_select_init = true; - } - update_ui(false); - } - } - break; - case TIMELINE_TOOL_HAND: - 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); - panel_timeline->selecting = true; - break; - case TIMELINE_TOOL_RAZOR: - { - panel_timeline->splitting = true; - panel_timeline->split_tracks.append(panel_timeline->drag_track_start); - update_ui(false); - } - break; - case TIMELINE_TOOL_TRANSITION: - { - if (panel_timeline->transition_tool_pre_clip > -1) { - panel_timeline->transition_tool_init = true; - } - } - break; - } - } - } + panel_timeline->rect_select_init = true; + } + update_ui(false); + } + } + break; + case TIMELINE_TOOL_HAND: + 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); + panel_timeline->selecting = true; + break; + case TIMELINE_TOOL_RAZOR: + { + panel_timeline->splitting = true; + panel_timeline->split_tracks.append(panel_timeline->drag_track_start); + update_ui(false); + } + break; + case TIMELINE_TOOL_TRANSITION: + { + if (panel_timeline->transition_tool_pre_clip > -1) { + panel_timeline->transition_tool_init = true; + } + } + break; + } + } + } } void make_room_for_transition(ComboAction* ca, ClipPtr c, int type, long transition_start, long transition_end, bool delete_old_transitions) { - // make room for transition - if (type == kTransitionOpening) { - if (delete_old_transitions && c->get_opening_transition() != nullptr) { + // make room for transition + if (type == kTransitionOpening) { + if (delete_old_transitions && c->get_opening_transition() != nullptr) { ca->append(new DeleteTransitionCommand(c->opening_transition)); - } - if (c->get_closing_transition() != nullptr) { - if (transition_end >= c->timeline_out) { + } + if (c->get_closing_transition() != nullptr) { + if (transition_end >= c->timeline_out) { ca->append(new DeleteTransitionCommand(c->closing_transition)); - } else if (transition_end > c->timeline_out - c->get_closing_transition()->get_true_length()) { + } else if (transition_end > c->timeline_out - c->get_closing_transition()->get_true_length()) { ca->append(new ModifyTransitionCommand(c->closing_transition, c->timeline_out - transition_end)); - } - } - } else { - if (delete_old_transitions && c->get_closing_transition() != nullptr) { + } + } + } else { + if (delete_old_transitions && c->get_closing_transition() != nullptr) { ca->append(new DeleteTransitionCommand(c->closing_transition)); - } - if (c->get_opening_transition() != nullptr) { - if (transition_start <= c->timeline_in) { + } + if (c->get_opening_transition() != nullptr) { + if (transition_start <= c->timeline_in) { ca->append(new DeleteTransitionCommand(c->opening_transition)); - } else if (transition_start < c->timeline_in + c->get_opening_transition()->get_true_length()) { + } else if (transition_start < c->timeline_in + c->get_opening_transition()->get_true_length()) { ca->append(new ModifyTransitionCommand(c->opening_transition, transition_start - c->timeline_in)); - } - } - } + } + } + } } void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { - QToolTip::hideText(); - if (olive::ActiveSequence != nullptr) { - bool alt = (event->modifiers() & Qt::AltModifier); - bool shift = (event->modifiers() & Qt::ShiftModifier); - bool ctrl = (event->modifiers() & Qt::ControlModifier); + QToolTip::hideText(); + if (olive::ActiveSequence != nullptr) { + bool alt = (event->modifiers() & Qt::AltModifier); + bool shift = (event->modifiers() & Qt::ShiftModifier); + bool ctrl = (event->modifiers() & Qt::ControlModifier); - if (event->button() == Qt::LeftButton) { - ComboAction* ca = new ComboAction(); - bool push_undo = false; + if (event->button() == Qt::LeftButton) { + ComboAction* ca = new ComboAction(); + bool push_undo = false; - if (panel_timeline->creating) { - if (panel_timeline->ghosts.size() > 0) { - const Ghost& g = panel_timeline->ghosts.at(0); + if (panel_timeline->creating) { + if (panel_timeline->ghosts.size() > 0) { + const Ghost& g = panel_timeline->ghosts.at(0); - if (panel_timeline->creating_object == ADD_OBJ_AUDIO) { - olive::MainWindow->statusBar()->clearMessage(); - panel_sequence_viewer->cue_recording(qMin(g.in, g.out), qMax(g.in, g.out), g.track); - panel_timeline->creating = false; - } else if (g.in != g.out) { - ClipPtr c = ClipPtr(new Clip(olive::ActiveSequence)); - c->media = nullptr; - c->timeline_in = qMin(g.in, g.out); - c->timeline_out = qMax(g.in, g.out); - c->clip_in = 0; - c->color_r = 192; - c->color_g = 192; - c->color_b = 64; - c->track = g.track; + if (panel_timeline->creating_object == ADD_OBJ_AUDIO) { + olive::MainWindow->statusBar()->clearMessage(); + panel_sequence_viewer->cue_recording(qMin(g.in, g.out), qMax(g.in, g.out), g.track); + panel_timeline->creating = false; + } else if (g.in != g.out) { + ClipPtr c = ClipPtr(new Clip(olive::ActiveSequence)); + c->media = nullptr; + c->timeline_in = qMin(g.in, g.out); + c->timeline_out = qMax(g.in, g.out); + c->clip_in = 0; + c->color_r = 192; + c->color_g = 192; + c->color_b = 64; + c->track = g.track; - if (ctrl) { - insert_clips(ca); - } else { - Selection s; - s.in = c->timeline_in; - s.out = c->timeline_out; - s.track = c->track; - QVector areas; - areas.append(s); - panel_timeline->delete_areas_and_relink(ca, areas, false); - } + if (ctrl) { + insert_clips(ca); + } else { + Selection s; + s.in = c->timeline_in; + s.out = c->timeline_out; + s.track = c->track; + QVector areas; + areas.append(s); + panel_timeline->delete_areas_and_relink(ca, areas, false); + } - QVector add; - add.append(c); - ca->append(new AddClipCommand(olive::ActiveSequence, add)); + QVector add; + add.append(c); + ca->append(new AddClipCommand(olive::ActiveSequence, add)); - if (c->track < 0 && olive::CurrentConfig.add_default_effects_to_clips) { - // default video effects (before custom effects) - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TRANSFORM, EFFECT_TYPE_EFFECT))); - } + if (c->track < 0 && olive::CurrentConfig.add_default_effects_to_clips) { + // default video effects (before custom effects) + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TRANSFORM, EFFECT_TYPE_EFFECT))); + } - switch (panel_timeline->creating_object) { - case ADD_OBJ_TITLE: - c->name = tr("Title"); - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TEXT, EFFECT_TYPE_EFFECT))); - break; - case ADD_OBJ_SOLID: - c->name = tr("Solid Color"); - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_SOLID, EFFECT_TYPE_EFFECT))); - break; - case ADD_OBJ_BARS: - { - c->name = tr("Bars"); - EffectPtr e = create_effect(c, get_internal_meta(EFFECT_INTERNAL_SOLID, EFFECT_TYPE_EFFECT)); - e->row(0)->field(0)->set_combo_index(1); - c->effects.append(e); - } - break; - case ADD_OBJ_TONE: - c->name = tr("Tone"); - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TONE, EFFECT_TYPE_EFFECT))); - break; - case ADD_OBJ_NOISE: - c->name = tr("Noise"); - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_NOISE, EFFECT_TYPE_EFFECT))); - break; - } + switch (panel_timeline->creating_object) { + case ADD_OBJ_TITLE: + c->name = tr("Title"); + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TEXT, EFFECT_TYPE_EFFECT))); + break; + case ADD_OBJ_SOLID: + c->name = tr("Solid Color"); + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_SOLID, EFFECT_TYPE_EFFECT))); + break; + case ADD_OBJ_BARS: + { + c->name = tr("Bars"); + EffectPtr e = create_effect(c, get_internal_meta(EFFECT_INTERNAL_SOLID, EFFECT_TYPE_EFFECT)); + e->row(0)->field(0)->set_combo_index(1); + c->effects.append(e); + } + break; + case ADD_OBJ_TONE: + c->name = tr("Tone"); + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TONE, EFFECT_TYPE_EFFECT))); + break; + case ADD_OBJ_NOISE: + c->name = tr("Noise"); + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_NOISE, EFFECT_TYPE_EFFECT))); + break; + } - if (c->track >= 0 && olive::CurrentConfig.add_default_effects_to_clips) { - // default audio effects (after custom effects) - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_VOLUME, EFFECT_TYPE_EFFECT))); - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_PAN, EFFECT_TYPE_EFFECT))); - } + if (c->track >= 0 && olive::CurrentConfig.add_default_effects_to_clips) { + // default audio effects (after custom effects) + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_VOLUME, EFFECT_TYPE_EFFECT))); + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_PAN, EFFECT_TYPE_EFFECT))); + } - push_undo = true; + push_undo = true; - if (!shift) { - panel_timeline->creating = false; - } - } - } - } else if (panel_timeline->moving_proc) { - bool process_moving = false; + if (!shift) { + panel_timeline->creating = false; + } + } + } + } else if (panel_timeline->moving_proc) { + bool process_moving = false; - for (int i=0;ighosts.size();i++) { - const Ghost& g = panel_timeline->ghosts.at(i); - if (g.in != g.old_in - || g.out != g.old_out - || g.clip_in != g.old_clip_in - || g.track != g.old_track) { - process_moving = true; - break; - } - } + for (int i=0;ighosts.size();i++) { + const Ghost& g = panel_timeline->ghosts.at(i); + if (g.in != g.old_in + || g.out != g.old_out + || g.clip_in != g.old_clip_in + || g.track != g.old_track) { + process_moving = true; + break; + } + } - if (process_moving) { - const Ghost& first_ghost = panel_timeline->ghosts.at(0); + if (process_moving) { + const Ghost& first_ghost = panel_timeline->ghosts.at(0); - // if we were RIPPLING, move all the clips - if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) { - long ripple_length, ripple_point; + // if we were RIPPLING, move all the clips + if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) { + long ripple_length, ripple_point; - // ripple_length becomes the length/number of frames we trimmed - // ripple point becomes the point to ripple (i.e. the point after or before which we move every clip) - if (panel_timeline->trim_in_point) { - ripple_length = first_ghost.old_in - first_ghost.in; - ripple_point = first_ghost.old_in; + // 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) { + ripple_length = first_ghost.old_in - first_ghost.in; + ripple_point = first_ghost.old_in; - for (int i=0;iselections.size();i++) { - olive::ActiveSequence->selections[i].in += ripple_length; - olive::ActiveSequence->selections[i].out += ripple_length; - } - } else { - // if we're trimming an out-point - ripple_length = first_ghost.old_out - panel_timeline->ghosts.at(0).out; - ripple_point = first_ghost.old_out; - } - QVector ignore_clips; - for (int i=0;ighosts.size();i++) { - const Ghost& g = panel_timeline->ghosts.at(i); + for (int i=0;iselections.size();i++) { + olive::ActiveSequence->selections[i].in += ripple_length; + olive::ActiveSequence->selections[i].out += ripple_length; + } + } else { + // if we're trimming an out-point + ripple_length = first_ghost.old_out - panel_timeline->ghosts.at(0).out; + ripple_point = first_ghost.old_out; + } + QVector ignore_clips; + for (int i=0;ighosts.size();i++) { + const Ghost& g = panel_timeline->ghosts.at(i); - // push rippled clips forward if necessary - if (panel_timeline->trim_in_point) { - ignore_clips.append(g.clip); - panel_timeline->ghosts[i].in += ripple_length; - panel_timeline->ghosts[i].out += ripple_length; - } + // push rippled clips forward if necessary + if (panel_timeline->trim_in_point) { + 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; - ripple_point = qMin(ripple_point, comp_point); - } - if (!panel_timeline->trim_in_point) ripple_length = -ripple_length; + long comp_point = panel_timeline->trim_in_point ? g.old_in : g.old_out; + ripple_point = qMin(ripple_point, comp_point); + } + if (!panel_timeline->trim_in_point) ripple_length = -ripple_length; - ripple_clips(ca, olive::ActiveSequence, ripple_point, ripple_length, ignore_clips); - } + ripple_clips(ca, olive::ActiveSequence, ripple_point, ripple_length, ignore_clips); + } - if (panel_timeline->tool == TIMELINE_TOOL_POINTER - && (event->modifiers() & Qt::AltModifier) - && panel_timeline->trim_target == -1) { // if holding alt (and not trimming), duplicate rather than move - // duplicate clips - QVector old_clips; - QVector new_clips; - QVector delete_areas; - for (int i=0;ighosts.size();i++) { - const Ghost& g = panel_timeline->ghosts.at(i); - if (g.old_in != g.in || g.old_out != g.out || g.track != g.old_track || g.clip_in != g.old_clip_in) { - // create copy of clip - ClipPtr c(olive::ActiveSequence->clips.at(g.clip)->copy(olive::ActiveSequence)); + if (panel_timeline->tool == TIMELINE_TOOL_POINTER + && (event->modifiers() & Qt::AltModifier) + && panel_timeline->trim_target == -1) { // if holding alt (and not trimming), duplicate rather than move + // duplicate clips + QVector old_clips; + QVector new_clips; + QVector delete_areas; + for (int i=0;ighosts.size();i++) { + const Ghost& g = panel_timeline->ghosts.at(i); + if (g.old_in != g.in || g.old_out != g.out || g.track != g.old_track || g.clip_in != g.old_clip_in) { + // create copy of clip + ClipPtr c(olive::ActiveSequence->clips.at(g.clip)->copy(olive::ActiveSequence)); - c->timeline_in = g.in; - c->timeline_out = g.out; - c->track = g.track; + c->timeline_in = g.in; + c->timeline_out = g.out; + c->track = g.track; - Selection s; - s.in = g.in; - s.out = g.out; - s.track = g.track; - delete_areas.append(s); + Selection s; + s.in = g.in; + s.out = g.out; + s.track = g.track; + delete_areas.append(s); - old_clips.append(g.clip); - new_clips.append(c); - } - } - if (new_clips.size() > 0) { - panel_timeline->delete_areas_and_relink(ca, delete_areas, false); + old_clips.append(g.clip); + new_clips.append(c); + } + } + if (new_clips.size() > 0) { + panel_timeline->delete_areas_and_relink(ca, delete_areas, false); - // relink duplicated clips - panel_timeline->relink_clips_using_ids(old_clips, new_clips); + // relink duplicated clips + panel_timeline->relink_clips_using_ids(old_clips, new_clips); - ca->append(new AddClipCommand(olive::ActiveSequence, new_clips)); - } - } else { - // INSERT if holding ctrl - if (panel_timeline->tool == TIMELINE_TOOL_POINTER && ctrl) { - insert_clips(ca); - } else if (panel_timeline->tool == TIMELINE_TOOL_POINTER || panel_timeline->tool == TIMELINE_TOOL_SLIDE) { - // move clips - QVector delete_areas; - for (int i=0;ighosts.size();i++) { - // step 1 - set clips that are moving to "undeletable" (to avoid step 2 deleting any part of them) - const Ghost& g = panel_timeline->ghosts.at(i); + ca->append(new AddClipCommand(olive::ActiveSequence, new_clips)); + } + } else { + // INSERT if holding ctrl + if (panel_timeline->tool == TIMELINE_TOOL_POINTER && ctrl) { + insert_clips(ca); + } else if (panel_timeline->tool == TIMELINE_TOOL_POINTER || panel_timeline->tool == TIMELINE_TOOL_SLIDE) { + // move clips + QVector delete_areas; + for (int i=0;ighosts.size();i++) { + // step 1 - set clips that are moving to "undeletable" (to avoid step 2 deleting any part of them) + const Ghost& g = panel_timeline->ghosts.at(i); - olive::ActiveSequence->clips.at(g.clip)->undeletable = true; - if (g.transition != nullptr) { - g.transition->parent_clip->undeletable = true; - if (g.transition->secondary_clip != nullptr) g.transition->secondary_clip->undeletable = true; - } + olive::ActiveSequence->clips.at(g.clip)->undeletable = true; + if (g.transition != nullptr) { + g.transition->parent_clip->undeletable = true; + if (g.transition->secondary_clip != nullptr) g.transition->secondary_clip->undeletable = true; + } - Selection s; - s.in = g.in; - s.out = g.out; - s.track = g.track; - delete_areas.append(s); - } - panel_timeline->delete_areas_and_relink(ca, delete_areas, false); - for (int i=0;ighosts.size();i++) { - const Ghost& g = panel_timeline->ghosts.at(i); - olive::ActiveSequence->clips.at(g.clip)->undeletable = false; - if (g.transition != nullptr) { - g.transition->parent_clip->undeletable = false; - if (g.transition->secondary_clip != nullptr) g.transition->secondary_clip->undeletable = false; - } - } - } - for (int i=0;ighosts.size();i++) { - Ghost& g = panel_timeline->ghosts[i]; + Selection s; + s.in = g.in; + s.out = g.out; + s.track = g.track; + delete_areas.append(s); + } + panel_timeline->delete_areas_and_relink(ca, delete_areas, false); + for (int i=0;ighosts.size();i++) { + const Ghost& g = panel_timeline->ghosts.at(i); + olive::ActiveSequence->clips.at(g.clip)->undeletable = false; + if (g.transition != nullptr) { + g.transition->parent_clip->undeletable = false; + if (g.transition->secondary_clip != nullptr) g.transition->secondary_clip->undeletable = false; + } + } + } + for (int i=0;ighosts.size();i++) { + Ghost& g = panel_timeline->ghosts[i]; - // step 3 - move clips - ClipPtr c = olive::ActiveSequence->clips.at(g.clip); - if (g.transition == nullptr) { - move_clip(ca, c, (g.in - g.old_in), (g.out - g.old_out), (g.clip_in - g.old_clip_in), (g.track - g.old_track), true, true); + // step 3 - move clips + ClipPtr c = olive::ActiveSequence->clips.at(g.clip); + if (g.transition == nullptr) { + move_clip(ca, c, (g.in - g.old_in), (g.out - g.old_out), (g.clip_in - g.old_clip_in), (g.track - g.old_track), true, true); - // adjust transitions if we need to - 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) { - max_open_length -= c->get_closing_transition()->get_true_length(); - } - if (max_open_length <= 0) { - ca->append(new DeleteTransitionCommand(c->opening_transition)); - } else if (c->get_opening_transition()->get_true_length() > max_open_length) { - ca->append(new ModifyTransitionCommand(c->opening_transition, max_open_length)); - } - } - if (c->get_closing_transition() != nullptr) { - long max_open_length = new_clip_length; - if (c->get_opening_transition() != nullptr && panel_timeline->trim_in_point) { - max_open_length -= c->get_opening_transition()->get_true_length(); - } - if (max_open_length <= 0) { - ca->append(new DeleteTransitionCommand(c->closing_transition)); - } else if (c->get_closing_transition()->get_true_length() > max_open_length) { - ca->append(new ModifyTransitionCommand(c->closing_transition, max_open_length)); - } - } - } else { - bool is_opening_transition = (g.transition == c->get_opening_transition()); - long new_transition_length = g.out - g.in; - if (g.transition->secondary_clip != nullptr) new_transition_length >>= 1; - ca->append(new ModifyTransitionCommand(is_opening_transition ? c->opening_transition : c->closing_transition, new_transition_length)); + // adjust transitions if we need to + 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) { + max_open_length -= c->get_closing_transition()->get_true_length(); + } + if (max_open_length <= 0) { + ca->append(new DeleteTransitionCommand(c->opening_transition)); + } else if (c->get_opening_transition()->get_true_length() > max_open_length) { + ca->append(new ModifyTransitionCommand(c->opening_transition, max_open_length)); + } + } + if (c->get_closing_transition() != nullptr) { + long max_open_length = new_clip_length; + if (c->get_opening_transition() != nullptr && panel_timeline->trim_in_point) { + max_open_length -= c->get_opening_transition()->get_true_length(); + } + if (max_open_length <= 0) { + ca->append(new DeleteTransitionCommand(c->closing_transition)); + } else if (c->get_closing_transition()->get_true_length() > max_open_length) { + ca->append(new ModifyTransitionCommand(c->closing_transition, max_open_length)); + } + } + } else { + bool is_opening_transition = (g.transition == c->get_opening_transition()); + long new_transition_length = g.out - g.in; + if (g.transition->secondary_clip != nullptr) new_transition_length >>= 1; + ca->append(new ModifyTransitionCommand(is_opening_transition ? c->opening_transition : c->closing_transition, new_transition_length)); - long clip_length = c->getLength(); + long clip_length = c->getLength(); - if (g.transition->secondary_clip != nullptr) { - if (g.in != g.old_in && !g.trimming) { - 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); - } - } else if (is_opening_transition) { - if (g.in != g.old_in) { - // if transition is going to make the clip bigger, make the clip bigger - move_clip(ca, c, (g.in - g.old_in), 0, (g.clip_in - g.old_clip_in), 0, true, true); - clip_length -= (g.in - g.old_in); - } + if (g.transition->secondary_clip != nullptr) { + if (g.in != g.old_in && !g.trimming) { + 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); + } + } else if (is_opening_transition) { + if (g.in != g.old_in) { + // if transition is going to make the clip bigger, make the clip bigger + move_clip(ca, c, (g.in - g.old_in), 0, (g.clip_in - g.old_clip_in), 0, true, true); + clip_length -= (g.in - g.old_in); + } - make_room_for_transition(ca, c, kTransitionOpening, g.in, g.out, false); - } else { - if (g.out != g.old_out) { - // if transition is going to make the clip bigger, make the clip bigger - move_clip(ca, c, 0, (g.out - g.old_out), 0, 0, true, true); - clip_length += (g.out - g.old_out); - } + make_room_for_transition(ca, c, kTransitionOpening, g.in, g.out, false); + } else { + if (g.out != g.old_out) { + // if transition is going to make the clip bigger, make the clip bigger + move_clip(ca, c, 0, (g.out - g.old_out), 0, 0, true, true); + clip_length += (g.out - g.old_out); + } - make_room_for_transition(ca, c, kTransitionClosing, g.in, g.out, false); - } - } - } - } - push_undo = true; - } - } else if (panel_timeline->selecting || panel_timeline->rect_select_proc) { - } else if (panel_timeline->transition_tool_proc) { - const Ghost& g = panel_timeline->ghosts.at(0); + make_room_for_transition(ca, c, kTransitionClosing, g.in, g.out, false); + } + } + } + } + push_undo = true; + } + } else if (panel_timeline->selecting || panel_timeline->rect_select_proc) { + } else if (panel_timeline->transition_tool_proc) { + const Ghost& g = panel_timeline->ghosts.at(0); - if (g.in != g.out) { - long transition_start = qMin(g.in, g.out); - long transition_end = qMax(g.in, g.out); + if (g.in != g.out) { + long transition_start = qMin(g.in, g.out); + long transition_end = qMax(g.in, g.out); - ClipPtr pre = olive::ActiveSequence->clips.at(g.clip); - ClipPtr post = pre; + ClipPtr pre = olive::ActiveSequence->clips.at(g.clip); + ClipPtr post = pre; - make_room_for_transition(ca, pre, panel_timeline->transition_tool_type, transition_start, transition_end, true); + make_room_for_transition(ca, pre, panel_timeline->transition_tool_type, transition_start, transition_end, true); - if (panel_timeline->transition_tool_post_clip > -1) { - post = olive::ActiveSequence->clips.at(panel_timeline->transition_tool_post_clip); - int opposite_type = (panel_timeline->transition_tool_type == kTransitionOpening) ? kTransitionClosing : kTransitionOpening; - make_room_for_transition( - ca, - post, - opposite_type, - transition_start, - transition_end, - true - ); + if (panel_timeline->transition_tool_post_clip > -1) { + post = olive::ActiveSequence->clips.at(panel_timeline->transition_tool_post_clip); + int opposite_type = (panel_timeline->transition_tool_type == kTransitionOpening) ? kTransitionClosing : kTransitionOpening; + make_room_for_transition( + ca, + post, + opposite_type, + transition_start, + transition_end, + true + ); - if (panel_timeline->transition_tool_type == kTransitionClosing) { - // swap - ClipPtr temp = pre; - pre = post; - post = temp; - } - } + if (panel_timeline->transition_tool_type == kTransitionClosing) { + // swap + ClipPtr temp = pre; + pre = post; + post = temp; + } + } - if (transition_start < post->timeline_in || transition_end > pre->timeline_out) { - // delete shit over there and extend timeline in - QVector areas; - Selection s; - s.track = post->track; + if (transition_start < post->timeline_in || transition_end > pre->timeline_out) { + // delete shit over there and extend timeline in + QVector areas; + Selection s; + s.track = post->track; - bool move_post = false; - bool move_pre = false; + bool move_post = false; + bool move_pre = false; - if (transition_start < post->timeline_in) { - s.in = transition_start; - s.out = post->timeline_in; - areas.append(s); - move_post = true; - } - if (transition_end > pre->timeline_out) { - s.in = pre->timeline_out; - s.out = transition_end; - areas.append(s); - move_pre = true; - } + if (transition_start < post->timeline_in) { + s.in = transition_start; + s.out = post->timeline_in; + areas.append(s); + move_post = true; + } + if (transition_end > pre->timeline_out) { + s.in = pre->timeline_out; + s.out = transition_end; + areas.append(s); + move_pre = true; + } - panel_timeline->delete_areas_and_relink(ca, areas, false); + panel_timeline->delete_areas_and_relink(ca, areas, false); - if (move_post) move_clip(ca, post, qMin(transition_start, post->timeline_in), post->timeline_out, post->clip_in - (post->timeline_in - transition_start), post->track); - if (move_pre) move_clip(ca, pre, pre->timeline_in, qMax(transition_end, pre->timeline_out), pre->clip_in, pre->track); - } + if (move_post) move_clip(ca, post, qMin(transition_start, post->timeline_in), post->timeline_out, post->clip_in - (post->timeline_in - transition_start), post->track); + if (move_pre) move_clip(ca, pre, pre->timeline_in, qMax(transition_end, pre->timeline_out), pre->clip_in, pre->track); + } - if (panel_timeline->transition_tool_post_clip > -1) { - ca->append(new AddTransitionCommand(pre, post, nullptr, panel_timeline->transition_tool_meta, kTransitionOpening, transition_end - pre->timeline_in)); - } else { - ca->append(new AddTransitionCommand(pre, nullptr, nullptr, panel_timeline->transition_tool_meta, panel_timeline->transition_tool_type, transition_end - transition_start)); - } + if (panel_timeline->transition_tool_post_clip > -1) { + ca->append(new AddTransitionCommand(pre, post, nullptr, panel_timeline->transition_tool_meta, kTransitionOpening, transition_end - pre->timeline_in)); + } else { + ca->append(new AddTransitionCommand(pre, nullptr, nullptr, panel_timeline->transition_tool_meta, panel_timeline->transition_tool_type, transition_end - transition_start)); + } - push_undo = true; - } - } else if (panel_timeline->splitting) { - bool split = false; - for (int i=0;isplit_tracks.size();i++) { - int split_index = getClipIndexFromCoords(panel_timeline->drag_frame_start, panel_timeline->split_tracks.at(i)); - if (split_index > -1 && panel_timeline->split_clip_and_relink(ca, split_index, panel_timeline->drag_frame_start, !alt)) { - split = true; - } - } - if (split) { - push_undo = true; - } - panel_timeline->split_cache.clear(); - } + push_undo = true; + } + } else if (panel_timeline->splitting) { + bool split = false; + for (int i=0;isplit_tracks.size();i++) { + int split_index = getClipIndexFromCoords(panel_timeline->drag_frame_start, panel_timeline->split_tracks.at(i)); + if (split_index > -1 && panel_timeline->split_clip_and_relink(ca, split_index, panel_timeline->drag_frame_start, !alt)) { + split = true; + } + } + if (split) { + push_undo = true; + } + panel_timeline->split_cache.clear(); + } - // remove duplicate selections - panel_timeline->clean_up_selections(olive::ActiveSequence->selections); + // remove duplicate selections + panel_timeline->clean_up_selections(olive::ActiveSequence->selections); - if (selection_command != nullptr) { - selection_command->new_data = olive::ActiveSequence->selections; - ca->append(selection_command); - selection_command = nullptr; - push_undo = true; - } + if (selection_command != nullptr) { + selection_command->new_data = olive::ActiveSequence->selections; + ca->append(selection_command); + selection_command = nullptr; + push_undo = true; + } - if (push_undo) { - olive::UndoStack.push(ca); - } else { - delete ca; - } + if (push_undo) { + olive::UndoStack.push(ca); + } else { + delete ca; + } - // destroy all ghosts - panel_timeline->ghosts.clear(); + // destroy all ghosts + panel_timeline->ghosts.clear(); - // clear split tracks - panel_timeline->split_tracks.clear(); + // clear split tracks + panel_timeline->split_tracks.clear(); - panel_timeline->selecting = false; - panel_timeline->moving_proc = false; - panel_timeline->moving_init = false; - panel_timeline->splitting = false; - panel_timeline->snapped = false; - panel_timeline->rect_select_init = false; - panel_timeline->rect_select_proc = false; - panel_timeline->transition_tool_init = false; - panel_timeline->transition_tool_proc = false; - pre_clips.clear(); - post_clips.clear(); + panel_timeline->selecting = false; + panel_timeline->moving_proc = false; + panel_timeline->moving_init = false; + panel_timeline->splitting = false; + panel_timeline->snapped = false; + panel_timeline->rect_select_init = false; + panel_timeline->rect_select_proc = false; + panel_timeline->transition_tool_init = false; + panel_timeline->transition_tool_proc = false; + pre_clips.clear(); + post_clips.clear(); - update_ui(true); - } - panel_timeline->hand_moving = false; - } + update_ui(true); + } + panel_timeline->hand_moving = false; + } } void TimelineWidget::init_ghosts() { - for (int i=0;ighosts.size();i++) { - Ghost& g = panel_timeline->ghosts[i]; - ClipPtr c = olive::ActiveSequence->clips.at(g.clip); + for (int i=0;ighosts.size();i++) { + Ghost& g = panel_timeline->ghosts[i]; + ClipPtr c = olive::ActiveSequence->clips.at(g.clip); - g.track = g.old_track = c->track; - g.clip_in = g.old_clip_in = c->clip_in; + g.track = g.old_track = c->track; + g.clip_in = g.old_clip_in = c->clip_in; - if (panel_timeline->tool == TIMELINE_TOOL_SLIP) { - g.clip_in = g.old_clip_in = c->get_clip_in_with_transition(); - g.in = g.old_in = c->get_timeline_in_with_transition(); - g.out = g.old_out = c->get_timeline_out_with_transition(); - g.ghost_length = g.old_out - g.old_in; - } else if (g.transition == nullptr) { - // this ghost is for a clip - g.in = g.old_in = c->timeline_in; - g.out = g.old_out = c->timeline_out; - g.ghost_length = g.old_out - g.old_in; - } else if (g.transition == c->get_opening_transition()) { - g.in = g.old_in = c->get_timeline_in_with_transition(); - g.ghost_length = c->get_opening_transition()->get_length(); - g.out = g.old_out = g.in + g.ghost_length; - } else if (g.transition == c->get_closing_transition()) { - g.out = g.old_out = c->get_timeline_out_with_transition(); - g.ghost_length = c->get_closing_transition()->get_length(); - g.in = g.old_in = g.out - g.ghost_length; - g.clip_in = g.old_clip_in = c->clip_in + c->getLength() - c->get_closing_transition()->get_true_length(); - } + if (panel_timeline->tool == TIMELINE_TOOL_SLIP) { + g.clip_in = g.old_clip_in = c->get_clip_in_with_transition(); + g.in = g.old_in = c->get_timeline_in_with_transition(); + g.out = g.old_out = c->get_timeline_out_with_transition(); + g.ghost_length = g.old_out - g.old_in; + } else if (g.transition == nullptr) { + // this ghost is for a clip + g.in = g.old_in = c->timeline_in; + g.out = g.old_out = c->timeline_out; + g.ghost_length = g.old_out - g.old_in; + } else if (g.transition == c->get_opening_transition()) { + g.in = g.old_in = c->get_timeline_in_with_transition(); + g.ghost_length = c->get_opening_transition()->get_length(); + g.out = g.old_out = g.in + g.ghost_length; + } else if (g.transition == c->get_closing_transition()) { + g.out = g.old_out = c->get_timeline_out_with_transition(); + g.ghost_length = c->get_closing_transition()->get_length(); + g.in = g.old_in = g.out - g.ghost_length; + g.clip_in = g.old_clip_in = c->clip_in + c->getLength() - c->get_closing_transition()->get_true_length(); + } - // used for trim ops - c->recalculateMaxLength(); - g.media_length = c->getMaximumLength(); - } - for (int i=0;iselections.size();i++) { - Selection& s = olive::ActiveSequence->selections[i]; - s.old_in = s.in; - s.old_out = s.out; - s.old_track = s.track; - } + // used for trim ops + c->recalculateMaxLength(); + g.media_length = c->getMaximumLength(); + } + for (int i=0;iselections.size();i++) { + Selection& s = olive::ActiveSequence->selections[i]; + s.old_in = s.in; + s.old_out = s.out; + s.old_track = s.track; + } } void validate_transitions(ClipPtr c, int transition_type, long& frame_diff) { - long validator; + long validator; - if (transition_type == kTransitionOpening) { - // prevent from going below 0 on the timeline - validator = c->timeline_in + frame_diff; - if (validator < 0) frame_diff -= validator; + if (transition_type == kTransitionOpening) { + // prevent from going below 0 on the timeline + validator = c->timeline_in + frame_diff; + if (validator < 0) frame_diff -= validator; - // prevent from going below 0 for the media - validator = c->clip_in + frame_diff; - if (validator < 0) frame_diff -= validator; + // prevent from going below 0 for the media + validator = c->clip_in + frame_diff; + if (validator < 0) frame_diff -= validator; - // prevent transition from exceeding media length - validator -= c->getMaximumLength(); - if (validator > 0) frame_diff -= validator; - } else { - // prevent from going below 0 on the timeline - validator = c->timeline_out + frame_diff; - if (validator < 0) frame_diff -= validator; + // prevent transition from exceeding media length + validator -= c->getMaximumLength(); + if (validator > 0) frame_diff -= validator; + } else { + // prevent from going below 0 on the timeline + validator = c->timeline_out + frame_diff; + if (validator < 0) frame_diff -= validator; - // prevent from going below 0 for the media - validator = c->clip_in + c->getLength() + frame_diff; - if (validator < 0) frame_diff -= validator; + // prevent from going below 0 for the media + validator = c->clip_in + c->getLength() + frame_diff; + if (validator < 0) frame_diff -= validator; - // prevent transition from exceeding media length - validator -= c->getMaximumLength(); - if (validator > 0) frame_diff -= validator; - } + // prevent transition from exceeding media length + validator -= c->getMaximumLength(); + if (validator > 0) frame_diff -= validator; + } } void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { - int effective_tool = panel_timeline->tool; - if (panel_timeline->importing || panel_timeline->creating) effective_tool = TIMELINE_TOOL_POINTER; + int effective_tool = panel_timeline->tool; + if (panel_timeline->importing || panel_timeline->creating) effective_tool = TIMELINE_TOOL_POINTER; - int mouse_track = getTrackFromScreenPoint(mouse_pos.y()); - long frame_diff = (lock_frame) ? 0 : panel_timeline->getTimelineFrameFromScreenPoint(mouse_pos.x()) - panel_timeline->drag_frame_start; - int track_diff = ((effective_tool == TIMELINE_TOOL_SLIDE || panel_timeline->transition_select != kTransitionNone) && !panel_timeline->importing) ? 0 : mouse_track - panel_timeline->drag_track_start; - long validator; - long earliest_in_point = LONG_MAX; + int mouse_track = getTrackFromScreenPoint(mouse_pos.y()); + long frame_diff = (lock_frame) ? 0 : panel_timeline->getTimelineFrameFromScreenPoint(mouse_pos.x()) - panel_timeline->drag_frame_start; + int track_diff = ((effective_tool == TIMELINE_TOOL_SLIDE || panel_timeline->transition_select != kTransitionNone) && !panel_timeline->importing) ? 0 : mouse_track - panel_timeline->drag_track_start; + long validator; + long earliest_in_point = LONG_MAX; - // first try to snap - long fm; + // first try to snap + long fm; - if (effective_tool != TIMELINE_TOOL_SLIP) { - // slipping doesn't move the clips so we don't bother snapping for it - for (int i=0;ighosts.size();i++) { - const Ghost& g = panel_timeline->ghosts.at(i); + if (effective_tool != TIMELINE_TOOL_SLIP) { + // slipping doesn't move the clips so we don't bother snapping for it + for (int i=0;ighosts.size();i++) { + const Ghost& g = panel_timeline->ghosts.at(i); - // snap ghost's in point - if (panel_timeline->trim_target == -1 || g.trim_in) { - fm = g.old_in + frame_diff; - if (panel_timeline->snap_to_timeline(&fm, true, true, true)) { - frame_diff = fm - g.old_in; - break; - } - } + // snap ghost's in point + if (panel_timeline->trim_target == -1 || g.trim_in) { + fm = g.old_in + frame_diff; + if (panel_timeline->snap_to_timeline(&fm, true, true, true)) { + frame_diff = fm - g.old_in; + break; + } + } - // snap ghost's out point - if (panel_timeline->trim_target == -1 || !g.trim_in) { - fm = g.old_out + frame_diff; - if (panel_timeline->snap_to_timeline(&fm, true, true, true)) { - frame_diff = fm - g.old_out; - break; - } - } + // snap ghost's out point + if (panel_timeline->trim_target == -1 || !g.trim_in) { + fm = g.old_out + frame_diff; + if (panel_timeline->snap_to_timeline(&fm, true, true, true)) { + frame_diff = fm - g.old_out; + break; + } + } - // if the ghost is attached to a clip, snap its markers too - if (panel_timeline->trim_target == -1 && g.clip >= 0) { - ClipPtr c = olive::ActiveSequence->clips.at(g.clip); - for (int j=0;jget_markers().size();j++) { - long marker_real_time = c->get_markers().at(j).frame + c->timeline_in - c->clip_in; - fm = marker_real_time + frame_diff; - if (panel_timeline->snap_to_timeline(&fm, true, true, true)) { - frame_diff = fm - marker_real_time; - break; - } - } - } - } - } + // if the ghost is attached to a clip, snap its markers too + if (panel_timeline->trim_target == -1 && g.clip >= 0) { + ClipPtr c = olive::ActiveSequence->clips.at(g.clip); + for (int j=0;jget_markers().size();j++) { + long marker_real_time = c->get_markers().at(j).frame + c->timeline_in - c->clip_in; + fm = marker_real_time + frame_diff; + if (panel_timeline->snap_to_timeline(&fm, true, true, true)) { + frame_diff = fm - marker_real_time; + break; + } + } + } + } + } - bool clips_are_movable = (effective_tool == TIMELINE_TOOL_POINTER || effective_tool == TIMELINE_TOOL_SLIDE); + bool clips_are_movable = (effective_tool == TIMELINE_TOOL_POINTER || effective_tool == TIMELINE_TOOL_SLIDE); - // validate ghosts - long temp_frame_diff = frame_diff; // cache to see if we change it (thus cancelling any snap) - for (int i=0;ighosts.size();i++) { - const Ghost& g = panel_timeline->ghosts.at(i); - ClipPtr c = nullptr; - if (g.clip != -1) c = olive::ActiveSequence->clips.at(g.clip); + // validate ghosts + long temp_frame_diff = frame_diff; // cache to see if we change it (thus cancelling any snap) + for (int i=0;ighosts.size();i++) { + const Ghost& g = panel_timeline->ghosts.at(i); + ClipPtr c = nullptr; + if (g.clip != -1) c = olive::ActiveSequence->clips.at(g.clip); - const FootageStream* ms = nullptr; - if (g.clip != -1 && c->media != nullptr && c->media->get_type() == MEDIA_TYPE_FOOTAGE) { - ms = c->media->to_footage()->get_stream_from_file_index(c->track < 0, c->media_stream); - } + const FootageStream* ms = nullptr; + if (g.clip != -1 && c->media != nullptr && c->media->get_type() == MEDIA_TYPE_FOOTAGE) { + ms = c->media->to_footage()->get_stream_from_file_index(c->track < 0, c->media_stream); + } - // validate ghosts for trimming - if (panel_timeline->creating) { - // i feel like we might need something here but we haven't so far? - } else if (effective_tool == TIMELINE_TOOL_SLIP) { - if ((c->media != nullptr && c->media->get_type() == MEDIA_TYPE_SEQUENCE) - || (ms != nullptr && !ms->infinite_length)) { - // prevent slip moving a clip below 0 clip_in - validator = g.old_clip_in - frame_diff; - if (validator < 0) frame_diff += validator; + // validate ghosts for trimming + if (panel_timeline->creating) { + // i feel like we might need something here but we haven't so far? + } else if (effective_tool == TIMELINE_TOOL_SLIP) { + if ((c->media != nullptr && c->media->get_type() == MEDIA_TYPE_SEQUENCE) + || (ms != nullptr && !ms->infinite_length)) { + // prevent slip moving a clip below 0 clip_in + validator = g.old_clip_in - frame_diff; + if (validator < 0) frame_diff += validator; - // prevent slip moving clip beyond media length - validator += g.ghost_length; - if (validator > g.media_length) frame_diff += validator - g.media_length; - } - } else if (g.trimming) { - if (g.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); + // prevent slip moving clip beyond media length + validator += g.ghost_length; + if (validator > g.media_length) frame_diff += validator - g.media_length; + } + } else if (g.trimming) { + if (g.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); - // prevent timeline in from going below 0 - if (effective_tool != TIMELINE_TOOL_RIPPLE) { - validator = g.old_in + frame_diff; - if (validator < 0) frame_diff -= validator; - } + // prevent timeline in from going below 0 + if (effective_tool != TIMELINE_TOOL_RIPPLE) { + validator = g.old_in + frame_diff; + if (validator < 0) frame_diff -= validator; + } - // prevent clip_in from going below 0 - if ((c->media != nullptr && c->media->get_type() == MEDIA_TYPE_SEQUENCE) - || (ms != nullptr && !ms->infinite_length)) { - validator = g.old_clip_in + frame_diff; - if (validator < 0) frame_diff -= validator; - } - } else { - // prevent clip length from being less than 1 frame long - validator = g.ghost_length + frame_diff; - if (validator < 1) frame_diff += (1 - validator); + // prevent clip_in from going below 0 + if ((c->media != nullptr && c->media->get_type() == MEDIA_TYPE_SEQUENCE) + || (ms != nullptr && !ms->infinite_length)) { + validator = g.old_clip_in + frame_diff; + if (validator < 0) frame_diff -= validator; + } + } else { + // prevent clip length from being less than 1 frame long + validator = g.ghost_length + frame_diff; + if (validator < 1) frame_diff += (1 - validator); - // prevent clip length exceeding media length - if ((c->media != nullptr && c->media->get_type() == MEDIA_TYPE_SEQUENCE) - || (ms != nullptr && !ms->infinite_length)) { - validator = g.old_clip_in + g.ghost_length + frame_diff; - if (validator > g.media_length) frame_diff -= validator - g.media_length; - } - } + // prevent clip length exceeding media length + if ((c->media != nullptr && c->media->get_type() == MEDIA_TYPE_SEQUENCE) + || (ms != nullptr && !ms->infinite_length)) { + validator = g.old_clip_in + g.ghost_length + frame_diff; + if (validator > g.media_length) frame_diff -= validator - g.media_length; + } + } - // prevent dual transition from going below 0 on the primary or media length on the secondary - if (g.transition != nullptr && g.transition->secondary_clip != nullptr) { - ClipPtr otc = g.transition->parent_clip; - ClipPtr ctc = g.transition->secondary_clip; + // prevent dual transition from going below 0 on the primary or media length on the secondary + if (g.transition != nullptr && g.transition->secondary_clip != nullptr) { + ClipPtr otc = g.transition->parent_clip; + ClipPtr ctc = g.transition->secondary_clip; - if (g.trim_in) { - frame_diff -= g.transition->get_true_length(); - } else { - frame_diff += g.transition->get_true_length(); - } + if (g.trim_in) { + frame_diff -= g.transition->get_true_length(); + } else { + frame_diff += g.transition->get_true_length(); + } - validate_transitions(otc, kTransitionOpening, frame_diff); - validate_transitions(ctc, kTransitionClosing, frame_diff); + validate_transitions(otc, kTransitionOpening, frame_diff); + validate_transitions(ctc, kTransitionClosing, frame_diff); - frame_diff = -frame_diff; - validate_transitions(otc, kTransitionOpening, frame_diff); - validate_transitions(ctc, kTransitionClosing, frame_diff); - frame_diff = -frame_diff; + frame_diff = -frame_diff; + validate_transitions(otc, kTransitionOpening, frame_diff); + validate_transitions(ctc, kTransitionClosing, frame_diff); + frame_diff = -frame_diff; - if (g.trim_in) { - frame_diff += g.transition->get_true_length(); - } else { - frame_diff -= g.transition->get_true_length(); - } - } + if (g.trim_in) { + frame_diff += g.transition->get_true_length(); + } else { + frame_diff -= g.transition->get_true_length(); + } + } - // ripple ops - if (effective_tool == TIMELINE_TOOL_RIPPLE) { - for (int j=0;jtrim_in_point) { - validator = post->timeline_in - frame_diff; - if (validator < 0) frame_diff += validator; - } + // prevent any rippled clip from going below 0 + if (panel_timeline->trim_in_point) { + validator = post->timeline_in - frame_diff; + if (validator < 0) frame_diff += validator; + } - // prevent any post-clips colliding with pre-clips - for (int k=0;ktrack == post->track) { - if (panel_timeline->trim_in_point) { - validator = post->timeline_in - frame_diff - pre->timeline_out; - if (validator < 0) frame_diff += validator; - } else { - validator = post->timeline_in + frame_diff - pre->timeline_out; - if (validator < 0) frame_diff -= validator; - } - } - } - } - } - } else if (clips_are_movable) { // validate ghosts for moving - // prevent clips from moving below 0 on the timeline - validator = g.old_in + frame_diff; - if (validator < 0) frame_diff -= validator; + // prevent any post-clips colliding with pre-clips + for (int k=0;ktrack == post->track) { + if (panel_timeline->trim_in_point) { + validator = post->timeline_in - frame_diff - pre->timeline_out; + if (validator < 0) frame_diff += validator; + } else { + validator = post->timeline_in + frame_diff - pre->timeline_out; + if (validator < 0) frame_diff -= validator; + } + } + } + } + } + } else if (clips_are_movable) { // validate ghosts for moving + // prevent clips from moving below 0 on the timeline + validator = g.old_in + frame_diff; + if (validator < 0) frame_diff -= validator; - if (g.transition != nullptr) { - if (g.transition->secondary_clip != nullptr) { - // prevent dual transitions from going below 0 on the primary or above media length on the secondary + if (g.transition != nullptr) { + if (g.transition->secondary_clip != nullptr) { + // prevent dual transitions from going below 0 on the primary or above media length on the secondary - validator = g.transition->parent_clip->get_clip_in_with_transition() + frame_diff; - if (validator < 0) frame_diff -= validator; + validator = g.transition->parent_clip->get_clip_in_with_transition() + frame_diff; + if (validator < 0) frame_diff -= validator; - validator = g.transition->secondary_clip->get_timeline_out_with_transition() - g.transition->secondary_clip->get_timeline_in_with_transition() - g.transition->get_length() + g.transition->secondary_clip->get_clip_in_with_transition() + frame_diff; - if (validator < 0) frame_diff -= validator; + validator = g.transition->secondary_clip->get_timeline_out_with_transition() - g.transition->secondary_clip->get_timeline_in_with_transition() - g.transition->get_length() + g.transition->secondary_clip->get_clip_in_with_transition() + frame_diff; + if (validator < 0) frame_diff -= validator; - validator = g.transition->parent_clip->clip_in + frame_diff - g.transition->parent_clip->getMaximumLength() + g.transition->get_true_length(); - if (validator > 0) frame_diff -= validator; + validator = g.transition->parent_clip->clip_in + frame_diff - g.transition->parent_clip->getMaximumLength() + g.transition->get_true_length(); + if (validator > 0) frame_diff -= validator; - validator = g.transition->secondary_clip->get_timeline_out_with_transition() - g.transition->secondary_clip->get_timeline_in_with_transition() + g.transition->secondary_clip->get_clip_in_with_transition() + frame_diff - g.transition->secondary_clip->getMaximumLength(); - if (validator > 0) frame_diff -= validator; - } else { - // prevent clip_in from going below 0 - if (c->media->get_type() == MEDIA_TYPE_SEQUENCE - || (ms != nullptr && !ms->infinite_length)) { - validator = g.old_clip_in + frame_diff; - if (validator < 0) frame_diff -= validator; - } + validator = g.transition->secondary_clip->get_timeline_out_with_transition() - g.transition->secondary_clip->get_timeline_in_with_transition() + g.transition->secondary_clip->get_clip_in_with_transition() + frame_diff - g.transition->secondary_clip->getMaximumLength(); + if (validator > 0) frame_diff -= validator; + } else { + // prevent clip_in from going below 0 + if (c->media->get_type() == MEDIA_TYPE_SEQUENCE + || (ms != nullptr && !ms->infinite_length)) { + validator = g.old_clip_in + frame_diff; + if (validator < 0) frame_diff -= validator; + } - // prevent clip length exceeding media length - if (c->media->get_type() == MEDIA_TYPE_SEQUENCE - || (ms != nullptr && !ms->infinite_length)) { - validator = g.old_clip_in + g.ghost_length + frame_diff; - if (validator > g.media_length) frame_diff -= validator - g.media_length; - } - } - } + // prevent clip length exceeding media length + if (c->media->get_type() == MEDIA_TYPE_SEQUENCE + || (ms != nullptr && !ms->infinite_length)) { + validator = g.old_clip_in + g.ghost_length + frame_diff; + if (validator > g.media_length) frame_diff -= validator - g.media_length; + } + } + } - // prevent clips from crossing tracks - if (same_sign(g.old_track, panel_timeline->drag_track_start)) { - while (!same_sign(g.old_track, g.old_track + track_diff)) { - if (g.old_track < 0) { - track_diff--; - } else { - track_diff++; - } - } - } - } else if (effective_tool == TIMELINE_TOOL_TRANSITION) { - if (panel_timeline->transition_tool_post_clip == -1) { - validate_transitions(c, panel_timeline->transition_tool_type, frame_diff); - } else { - ClipPtr otc = c; // open transition clip - ClipPtr ctc = olive::ActiveSequence->clips.at(panel_timeline->transition_tool_post_clip); // close transition clip + // prevent clips from crossing tracks + if (same_sign(g.old_track, panel_timeline->drag_track_start)) { + while (!same_sign(g.old_track, g.old_track + track_diff)) { + if (g.old_track < 0) { + track_diff--; + } else { + track_diff++; + } + } + } + } else if (effective_tool == TIMELINE_TOOL_TRANSITION) { + if (panel_timeline->transition_tool_post_clip == -1) { + validate_transitions(c, panel_timeline->transition_tool_type, frame_diff); + } else { + ClipPtr otc = c; // open transition clip + ClipPtr ctc = olive::ActiveSequence->clips.at(panel_timeline->transition_tool_post_clip); // close transition clip - if (panel_timeline->transition_tool_type == kTransitionClosing) { - // swap - ClipPtr temp = otc; - otc = ctc; - ctc = temp; - } + if (panel_timeline->transition_tool_type == kTransitionClosing) { + // swap + ClipPtr temp = otc; + otc = ctc; + ctc = temp; + } - // always gets a positive frame_diff - validate_transitions(otc, kTransitionOpening, frame_diff); - validate_transitions(ctc, kTransitionClosing, frame_diff); + // always gets a positive frame_diff + validate_transitions(otc, kTransitionOpening, frame_diff); + validate_transitions(ctc, kTransitionClosing, frame_diff); - // always gets a negative frame_diff - frame_diff = -frame_diff; - validate_transitions(otc, kTransitionOpening, frame_diff); - validate_transitions(ctc, kTransitionClosing, frame_diff); - frame_diff = -frame_diff; - } - } - } - if (temp_frame_diff != frame_diff) panel_timeline->snapped = false; + // always gets a negative frame_diff + frame_diff = -frame_diff; + validate_transitions(otc, kTransitionOpening, frame_diff); + validate_transitions(ctc, kTransitionClosing, frame_diff); + frame_diff = -frame_diff; + } + } + } + if (temp_frame_diff != frame_diff) panel_timeline->snapped = false; - // apply changes to ghosts - for (int i=0;ighosts.size();i++) { - Ghost& g = panel_timeline->ghosts[i]; + // apply changes to ghosts + for (int i=0;ighosts.size();i++) { + Ghost& g = panel_timeline->ghosts[i]; - if (effective_tool == TIMELINE_TOOL_SLIP) { - g.clip_in = g.old_clip_in - frame_diff; - } else if (g.trimming) { - long ghost_diff = frame_diff; + if (effective_tool == TIMELINE_TOOL_SLIP) { + g.clip_in = g.old_clip_in - frame_diff; + } else if (g.trimming) { + long ghost_diff = frame_diff; - // prevent trimming clips from overlapping each other - for (int j=0;jghosts.size();j++) { - 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) { - validator = (g.old_in + ghost_diff) - comp.out; - if (validator < 0) ghost_diff -= validator; - } else if (comp.in > g.in) { - validator = (g.old_out + ghost_diff) - comp.in; - if (validator > 0) ghost_diff -= validator; - } - } - } + // prevent trimming clips from overlapping each other + for (int j=0;jghosts.size();j++) { + 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) { + validator = (g.old_in + ghost_diff) - comp.out; + if (validator < 0) ghost_diff -= validator; + } else if (comp.in > g.in) { + validator = (g.old_out + ghost_diff) - comp.in; + if (validator > 0) ghost_diff -= validator; + } + } + } - // apply changes - if (g.transition != nullptr && g.transition->secondary_clip != nullptr) { - if (g.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) { - g.in = g.old_in + ghost_diff; - g.clip_in = g.old_clip_in + ghost_diff; - } else { - g.out = g.old_out + ghost_diff; - } - } else if (clips_are_movable) { - g.track = g.old_track; - g.in = g.old_in + frame_diff; - g.out = g.old_out + frame_diff; + // apply changes + if (g.transition != nullptr && g.transition->secondary_clip != nullptr) { + if (g.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) { + g.in = g.old_in + ghost_diff; + g.clip_in = g.old_clip_in + ghost_diff; + } else { + g.out = g.old_out + ghost_diff; + } + } else if (clips_are_movable) { + g.track = g.old_track; + g.in = g.old_in + frame_diff; + g.out = g.old_out + frame_diff; - if (g.transition != nullptr && g.transition == olive::ActiveSequence->clips.at(g.clip)->get_opening_transition()) { - g.clip_in = g.old_clip_in + frame_diff; - } + if (g.transition != nullptr && g.transition == olive::ActiveSequence->clips.at(g.clip)->get_opening_transition()) { + g.clip_in = g.old_clip_in + frame_diff; + } - if (panel_timeline->importing) { - if ((panel_timeline->video_ghosts && mouse_track < 0) - || (panel_timeline->audio_ghosts && mouse_track >= 0)) { - int abs_track_diff = abs(track_diff); - if (g.old_track < 0) { // clip is video - g.track -= abs_track_diff; - } else { // clip is audio - g.track += abs_track_diff; - } - } - } else if (same_sign(g.old_track, panel_timeline->drag_track_start)) { - g.track += track_diff; - } - } else if (effective_tool == TIMELINE_TOOL_TRANSITION) { - if (panel_timeline->transition_tool_post_clip > -1) { - g.in = g.old_in - frame_diff; - g.out = g.old_out + frame_diff; - } else if (panel_timeline->transition_tool_type == kTransitionOpening) { - g.out = g.old_out + frame_diff; - } else { - g.in = g.old_in + frame_diff; - } - } + if (panel_timeline->importing) { + if ((panel_timeline->video_ghosts && mouse_track < 0) + || (panel_timeline->audio_ghosts && mouse_track >= 0)) { + int abs_track_diff = abs(track_diff); + if (g.old_track < 0) { // clip is video + g.track -= abs_track_diff; + } else { // clip is audio + g.track += abs_track_diff; + } + } + } else if (same_sign(g.old_track, panel_timeline->drag_track_start)) { + g.track += track_diff; + } + } else if (effective_tool == TIMELINE_TOOL_TRANSITION) { + if (panel_timeline->transition_tool_post_clip > -1) { + g.in = g.old_in - frame_diff; + g.out = g.old_out + frame_diff; + } else if (panel_timeline->transition_tool_type == kTransitionOpening) { + g.out = g.old_out + frame_diff; + } else { + g.in = g.old_in + frame_diff; + } + } - earliest_in_point = qMin(earliest_in_point, g.in); - } + earliest_in_point = qMin(earliest_in_point, g.in); + } - // apply changes to selections - if (effective_tool != TIMELINE_TOOL_SLIP && !panel_timeline->importing && !panel_timeline->creating) { + // apply changes to selections + if (effective_tool != TIMELINE_TOOL_SLIP && !panel_timeline->importing && !panel_timeline->creating) { + 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) { + s.in = s.old_in + frame_diff; + } else { + s.out = s.old_out + frame_diff; + } + } else if (clips_are_movable) { 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) { - s.in = s.old_in + frame_diff; - } else { - s.out = s.old_out + frame_diff; - } - } else if (clips_are_movable) { - for (int i=0;iselections.size();i++) { - Selection& s = olive::ActiveSequence->selections[i]; - s.in = s.old_in + frame_diff; - s.out = s.old_out + frame_diff; - s.track = s.old_track; + Selection& s = olive::ActiveSequence->selections[i]; + s.in = s.old_in + frame_diff; + s.out = s.old_out + frame_diff; + s.track = s.old_track; - if (panel_timeline->importing) { - int abs_track_diff = abs(track_diff); - if (s.old_track < 0) { - s.track -= abs_track_diff; - } else { - s.track += abs_track_diff; - } - } else { - if (same_sign(s.track, panel_timeline->drag_track_start)) s.track += track_diff; - } - } - } - } - } + if (panel_timeline->importing) { + int abs_track_diff = abs(track_diff); + if (s.old_track < 0) { + s.track -= abs_track_diff; + } else { + s.track += abs_track_diff; + } + } else { + if (same_sign(s.track, panel_timeline->drag_track_start)) s.track += track_diff; + } + } + } + } + } - if (panel_timeline->importing) { - QToolTip::showText(mapToGlobal(mouse_pos), frame_to_timecode(earliest_in_point, olive::CurrentConfig.timecode_view, olive::ActiveSequence->frame_rate)); - } else { - QString tip = ((frame_diff < 0) ? "-" : "+") + frame_to_timecode(qAbs(frame_diff), olive::CurrentConfig.timecode_view, olive::ActiveSequence->frame_rate); - if (panel_timeline->trim_target > -1) { - // find which clip is being moved - const Ghost* g = nullptr; - for (int i=0;ighosts.size();i++) { - if (panel_timeline->ghosts.at(i).clip == panel_timeline->trim_target) { - g = &panel_timeline->ghosts.at(i); - break; - } - } + if (panel_timeline->importing) { + QToolTip::showText(mapToGlobal(mouse_pos), frame_to_timecode(earliest_in_point, olive::CurrentConfig.timecode_view, olive::ActiveSequence->frame_rate)); + } else { + QString tip = ((frame_diff < 0) ? "-" : "+") + frame_to_timecode(qAbs(frame_diff), olive::CurrentConfig.timecode_view, olive::ActiveSequence->frame_rate); + if (panel_timeline->trim_target > -1) { + // find which clip is being moved + const Ghost* g = nullptr; + for (int i=0;ighosts.size();i++) { + if (panel_timeline->ghosts.at(i).clip == panel_timeline->trim_target) { + g = &panel_timeline->ghosts.at(i); + break; + } + } - if (g != nullptr) { - tip += " " + tr("Duration:") + " "; - long len = (g->old_out-g->old_in); - if (panel_timeline->trim_in_point) { - len -= frame_diff; - } else { - len += frame_diff; - } - tip += frame_to_timecode(len, olive::CurrentConfig.timecode_view, olive::ActiveSequence->frame_rate); - } - } - QToolTip::showText(mapToGlobal(mouse_pos), tip); - } + if (g != nullptr) { + tip += " " + tr("Duration:") + " "; + long len = (g->old_out-g->old_in); + if (panel_timeline->trim_in_point) { + len -= frame_diff; + } else { + len += frame_diff; + } + tip += frame_to_timecode(len, olive::CurrentConfig.timecode_view, olive::ActiveSequence->frame_rate); + } + } + QToolTip::showText(mapToGlobal(mouse_pos), tip); + } } void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { - tooltip_timer.stop(); - if (olive::ActiveSequence != nullptr) { - bool alt = (event->modifiers() & Qt::AltModifier); - - 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)); - - 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 (panel_timeline->selecting) { - int selection_count = 1 + qMax(panel_timeline->cursor_track, panel_timeline->drag_track_start) - qMin(panel_timeline->cursor_track, panel_timeline->drag_track_start) + panel_timeline->selection_offset; - if (olive::ActiveSequence->selections.size() != selection_count) { - olive::ActiveSequence->selections.resize(selection_count); - } - int minimum_selection_track = qMin(panel_timeline->cursor_track, panel_timeline->drag_track_start); - for (int i=panel_timeline->selection_offset;iselections[i]; - s.track = minimum_selection_track + i - panel_timeline->selection_offset; - long in = panel_timeline->drag_frame_start; - long out = panel_timeline->cursor_frame; - s.in = qMin(in, out); - s.out = qMax(in, out); - } - - // select linked clips too - if (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); - } - } - - break; - } - } - } - } - - if (olive::CurrentConfig.edit_tool_also_seeks) { - panel_sequence_viewer->seek(qMin(panel_timeline->drag_frame_start, panel_timeline->cursor_frame)); - } else { - panel_timeline->repaint_timeline(); - } - } else if (panel_timeline->hand_moving) { - 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; - - panel_timeline->repaint_timeline(); - - 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; - if (bottom_align) { - new_height += diff; - } else { - new_height -= diff; - } - new_height = qMax(new_height, olive::timeline::kTrackMinHeight); - panel_timeline->calculate_track_height(track_target, new_height); - update(); - } else if (panel_timeline->moving_proc) { - update_ghosts(event->pos(), event->modifiers() & Qt::ShiftModifier); - } else { - // set up movement - // create ghosts - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr) { - Ghost g; - g.transition = nullptr; - - 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 - 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); - } - } - } - - 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); - - // 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; - } - } - } - - // 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 - bool found = false; - int duplicate_ghost_index; - for (duplicate_ghost_index=0;duplicate_ghost_indexghosts.at(duplicate_ghost_index).clip == j) { - found = true; - break; - } - } - if (g.trim_in == panel_timeline->trim_in_point) { - if (!found) { - // add ghost for this clip with opposite trim_in - Ghost gh; - gh.transition = nullptr; - gh.clip = j; - gh.trimming = (panel_timeline->trim_target > -1); - gh.trim_in = !panel_timeline->trim_in_point; - panel_timeline->ghosts.append(gh); - } - } else { - if (found) { - panel_timeline->ghosts.removeAt(duplicate_ghost_index); - size--; - if (duplicate_ghost_index < i) i--; - } - } - } - } - } - } - } 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); - } - } - } - } - } - } - - init_ghosts(); - - // ripple edit prep - if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) { - long axis = LONG_MAX; - - 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) { - axis = qMin(axis, c->timeline_in); - } else { - axis = qMin(axis, c->timeline_out); - } - } - - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr && !is_clip_selected(c, true)) { - 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 - bool found = false; - QVector& clip_list = clip_is_post ? post_clips : pre_clips; - for (int j=0;jtrack == c->track) { - 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 (!found) { - clip_list.append(c); - } - } - } - } - - // store selections - selection_command = new SetSelectionsCommand(olive::ActiveSequence); - selection_command->old_data = olive::ActiveSequence->selections; - - panel_timeline->moving_proc = true; - } - update_ui(false); - } else if (panel_timeline->splitting) { - int track_start = qMin(panel_timeline->cursor_track, panel_timeline->drag_track_start); - int track_end = qMax(panel_timeline->cursor_track, panel_timeline->drag_track_start); - int track_size = 1 + track_end - track_start; - panel_timeline->split_tracks.resize(track_size); - for (int i=0;isplit_tracks[i] = track_start + i; - } - - if (!alt) { - for (int i=0;idrag_frame_start, panel_timeline->split_tracks[i]); - if (clip_index > -1) { - QVector tracks = panel_timeline->get_tracks_of_linked_clips(clip_index); - for (int j=0;j track_end) { - panel_timeline->split_tracks.append(tracks.at(j)); - } - } - } - } - } - 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()); - long frame_min = qMin(frame_start, frame_end); - long frame_max = qMax(frame_start, frame_end); - - int rsy = panel_timeline->rect_select_y; - if (bottom_align) rsy += height(); - int track_start = getTrackFromScreenPoint(rsy); - int track_end = getTrackFromScreenPoint(event->pos().y()); - int track_min = qMin(track_start, track_end); - int track_max = qMax(track_start, track_end); - - QVector selected_clips; - for (int i=0;iclips.size();i++) { - ClipPtr clip = olive::ActiveSequence->clips.at(i); - if (clip != nullptr && - clip->track >= track_min && - clip->track <= track_max && - !(clip->timeline_in < frame_min && clip->timeline_out < frame_min) && - !(clip->timeline_in > frame_max && clip->timeline_out > frame_max)) { - QVector session_clips; - session_clips.append(clip); - - if (!alt) { - for (int j=0;jlinked.size();j++) { - session_clips.append(olive::ActiveSequence->clips.at(clip->linked.at(j))); - } - } - - for (int j=0;jselections.resize(selected_clips.size() + panel_timeline->selection_offset); - for (int i=0;iselections[i+panel_timeline->selection_offset]; - ClipPtr clip = selected_clips.at(i); - s.old_in = s.in = clip->timeline_in; - s.old_out = s.out = clip->timeline_out; - s.old_track = s.track = clip->track; - } - - panel_timeline->repaint_timeline(); - } else { - panel_timeline->rect_select_x = event->pos().x(); - panel_timeline->rect_select_y = event->pos().y(); - if (bottom_align) panel_timeline->rect_select_y -= height(); - panel_timeline->rect_select_w = 0; - panel_timeline->rect_select_h = 0; - panel_timeline->rect_select_proc = true; - } - } else if (isLiveEditing()) { - // redraw because we have a cursor - panel_timeline->repaint_timeline(); - } else if (panel_timeline->tool == TIMELINE_TOOL_POINTER || - panel_timeline->tool == TIMELINE_TOOL_RIPPLE || - panel_timeline->tool == TIMELINE_TOOL_ROLLING) { - - // hide any tooltip that may be currently showing - QToolTip::hideText(); - - // cache cursor position - QPoint pos = event->pos(); - - // - // check to see if the cursor is on a clip edge - // - - // threshold around a trim point that the cursor can be within and still considered "trimming" - int lim = 5; - 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; - - // used to determine whether the cursor is within the rect of a clip - bool cursor_contains_clip = false; - - // used to determine how close the cursor is to a trim point - // (and more specifically, whether another point is closer or not) - int closeness = INT_MAX; - - // while we loop through the clips, we cache the maximum/minimum tracks in this sequence - int min_track = INT_MAX; - int max_track = INT_MIN; - - // we default to selecting no transition, but set this accordingly if the cursor is on a transition - panel_timeline->transition_select = kTransitionNone; - - // set currently trimming clip to -1 (aka null) - panel_timeline->trim_target = -1; - - // loop through current clips in the sequence - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr) { - - // cache track range - min_track = qMin(min_track, c->track); - max_track = qMax(max_track, c->track); - - // if this clip is on the same track the mouse is - if (c->track == mouse_track) { - - // if this cursor is inside the boundaries of this clip (hovering over the clip) - if (panel_timeline->cursor_frame >= c->timeline_in && - panel_timeline->cursor_frame <= c->timeline_out) { - - // acknowledge that we are hovering over a clip - cursor_contains_clip = true; - - // start a timer to show a tooltip about this clip - tooltip_timer.start(); - tooltip_clip = i; - - // check if the cursor is specifically hovering over one of the clip's transitions - if (c->get_opening_transition() != nullptr - && panel_timeline->cursor_frame <= c->timeline_in + c->get_opening_transition()->get_true_length()) { - - panel_timeline->transition_select = kTransitionOpening; - - } else if (c->get_closing_transition() != nullptr - && panel_timeline->cursor_frame >= c->timeline_out - c->get_closing_transition()->get_true_length()) { - - panel_timeline->transition_select = kTransitionClosing; - - } - } - - // is the cursor hovering around the clip's IN point? - if (c->timeline_in > mouse_frame_lower && c->timeline_in < mouse_frame_upper) { - - // test how close this IN point is to the cursor - int nc = qAbs(c->timeline_in + 1 - panel_timeline->cursor_frame); - - // and test whether it's closer than the last in/out point we found - if (nc < closeness) { - - // 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; - closeness = nc; - found = true; - - } - } - - // is the cursor hovering around the clip's OUT point? - if (c->timeline_out > mouse_frame_lower && c->timeline_out < mouse_frame_upper) { - - // test how close this OUT point is to the cursor - int nc = qAbs(c->timeline_out - 1 - panel_timeline->cursor_frame); - - // and test whether it's closer than the last in/out point we found - if (nc < closeness) { - - // 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; - closeness = nc; - found = true; - - } - } - - // the pointer can be used to resize/trim transitions, here we test if the - // cursor is within the trim point of one of the clip's transitions - if (panel_timeline->tool == TIMELINE_TOOL_POINTER) { - - // if the clip has an opening transition - if (c->get_opening_transition() != nullptr) { - - // cache the timeline frame where the transition ends - long transition_point = c->timeline_in + c->get_opening_transition()->get_true_length(); - - // check if the cursor is hovering around it (within the threshold) - if (transition_point > mouse_frame_lower && transition_point < mouse_frame_upper) { - - // similar to above, test how close it is and if it's closer, make this active - int nc = qAbs(transition_point - 1 - panel_timeline->cursor_frame); - if (nc < closeness) { - panel_timeline->trim_target = i; - panel_timeline->trim_in_point = false; - panel_timeline->transition_select = kTransitionOpening; - closeness = nc; - found = true; - } - } - } - - // if the clip has a closing transition - if (c->get_closing_transition() != nullptr) { - - // cache the timeline frame where the transition starts - long transition_point = c->timeline_out - c->get_closing_transition()->get_true_length(); - - // check if the cursor is hovering around it (within the threshold) - if (transition_point > mouse_frame_lower && transition_point < mouse_frame_upper) { - - // similar to above, test how close it is and if it's closer, make this active - int nc = qAbs(transition_point + 1 - panel_timeline->cursor_frame); - if (nc < closeness) { - panel_timeline->trim_target = i; - panel_timeline->trim_in_point = true; - panel_timeline->transition_select = kTransitionClosing; - closeness = nc; - found = true; - } - } - } - } - } - } + tooltip_timer.stop(); + if (olive::ActiveSequence != nullptr) { + bool alt = (event->modifiers() & Qt::AltModifier); + + 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)); + + 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 (panel_timeline->selecting) { + int selection_count = 1 + qMax(panel_timeline->cursor_track, panel_timeline->drag_track_start) - qMin(panel_timeline->cursor_track, panel_timeline->drag_track_start) + panel_timeline->selection_offset; + if (olive::ActiveSequence->selections.size() != selection_count) { + olive::ActiveSequence->selections.resize(selection_count); + } + int minimum_selection_track = qMin(panel_timeline->cursor_track, panel_timeline->drag_track_start); + for (int i=panel_timeline->selection_offset;iselections[i]; + s.track = minimum_selection_track + i - panel_timeline->selection_offset; + long in = panel_timeline->drag_frame_start; + long out = panel_timeline->cursor_frame; + s.in = qMin(in, out); + s.out = qMax(in, out); + } + + // select linked clips too + if (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); + } + } + + break; + } + } + } + } + + if (olive::CurrentConfig.edit_tool_also_seeks) { + panel_sequence_viewer->seek(qMin(panel_timeline->drag_frame_start, panel_timeline->cursor_frame)); + } else { + panel_timeline->repaint_timeline(); + } + } else if (panel_timeline->hand_moving) { + 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; + + panel_timeline->repaint_timeline(); + + 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; + if (bottom_align) { + new_height += diff; + } else { + new_height -= diff; + } + new_height = qMax(new_height, olive::timeline::kTrackMinHeight); + panel_timeline->calculate_track_height(track_target, new_height); + update(); + } else if (panel_timeline->moving_proc) { + update_ghosts(event->pos(), event->modifiers() & Qt::ShiftModifier); + } else { + // set up movement + // create ghosts + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr) { + Ghost g; + g.transition = nullptr; + + 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 + 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 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 - setCursor(olive::Cursor_LeftTrim); - } else { // if we're trimming an OUT point - setCursor(olive::Cursor_RightTrim); + 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; } + } + } - } else { - // we didn't find a trim target, so we must be doing something else - // (e.g. dragging a clip or resizing the track heights) + 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); + } + } + } - // 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 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 (found) { - setCursor(Qt::SizeVerCursor); - } else { - unsetCursor(); - } - } - } else if (panel_timeline->tool == TIMELINE_TOOL_SLIP) { - if (getClipIndexFromCoords(panel_timeline->cursor_frame, panel_timeline->cursor_track) > -1) { - setCursor(Qt::SizeHorCursor); - } else { - unsetCursor(); - } - } else if (panel_timeline->tool == TIMELINE_TOOL_TRANSITION) { - if (panel_timeline->transition_tool_init) { - if (panel_timeline->transition_tool_proc) { - update_ghosts(event->pos(), event->modifiers() & Qt::ShiftModifier); - } else { - ClipPtr c = olive::ActiveSequence->clips.at(panel_timeline->transition_tool_pre_clip); + // 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; + } + } + } - Ghost g; + // 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 + bool found = false; + int duplicate_ghost_index; + for (duplicate_ghost_index=0;duplicate_ghost_indexghosts.at(duplicate_ghost_index).clip == j) { + found = true; + break; + } + } + if (g.trim_in == panel_timeline->trim_in_point) { + if (!found) { + // add ghost for this clip with opposite trim_in + Ghost gh; + gh.transition = nullptr; + gh.clip = j; + gh.trimming = (panel_timeline->trim_target > -1); + gh.trim_in = !panel_timeline->trim_in_point; + panel_timeline->ghosts.append(gh); + } + } else { + if (found) { + panel_timeline->ghosts.removeAt(duplicate_ghost_index); + size--; + if (duplicate_ghost_index < i) i--; + } + } + } + } + } + } + } 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); + } + } + } + } + } + } - g.in = g.old_in = g.out = g.old_out = (panel_timeline->transition_tool_type == kTransitionOpening) ? c->timeline_in : c->timeline_out; - g.track = c->track; - g.clip = panel_timeline->transition_tool_pre_clip; - g.media_stream = panel_timeline->transition_tool_type; - g.trimming = false; + init_ghosts(); - panel_timeline->ghosts.append(g); + // ripple edit prep + if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) { + long axis = LONG_MAX; - panel_timeline->transition_tool_proc = true; - } - } else { - int mouse_clip = getClipIndexFromCoords(panel_timeline->cursor_frame, panel_timeline->cursor_track); - if (mouse_clip > -1) { - ClipPtr c = olive::ActiveSequence->clips.at(mouse_clip); - if (same_sign(c->track, panel_timeline->transition_tool_side)) { - panel_timeline->transition_tool_pre_clip = mouse_clip; - long halfway = c->timeline_in + (c->getLength()/2); - long between_range = getFrameFromScreenPoint(panel_timeline->zoom, TRANSITION_BETWEEN_RANGE) + 1; + 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) { + axis = qMin(axis, c->timeline_in); + } else { + axis = qMin(axis, c->timeline_out); + } + } - if (panel_timeline->cursor_frame > halfway) { - panel_timeline->transition_tool_type = kTransitionClosing; - } else { - panel_timeline->transition_tool_type = kTransitionOpening; - } + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr && !is_clip_selected(c, true)) { + bool clip_is_post = (c->timeline_in >= axis); - panel_timeline->transition_tool_post_clip = -1; - if (panel_timeline->cursor_frame < c->timeline_in + between_range) { - panel_timeline->transition_tool_post_clip = getClipIndexFromCoords(c->timeline_in-1, c->track); - } else if (panel_timeline->cursor_frame > c->timeline_out - between_range) { - panel_timeline->transition_tool_post_clip = getClipIndexFromCoords(c->timeline_out+1, c->track); - } - } - } else { - panel_timeline->transition_tool_pre_clip = -1; - panel_timeline->transition_tool_post_clip = -1; - } - } + // see if this a clip on this track is already in the list, and if it's closer + bool found = false; + QVector& clip_list = clip_is_post ? post_clips : pre_clips; + for (int j=0;jtrack == c->track) { + 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 (!found) { + clip_list.append(c); + } + } + } + } - panel_timeline->repaint_timeline(); - } - } + // store selections + selection_command = new SetSelectionsCommand(olive::ActiveSequence); + selection_command->old_data = olive::ActiveSequence->selections; + + panel_timeline->moving_proc = true; + } + update_ui(false); + } else if (panel_timeline->splitting) { + int track_start = qMin(panel_timeline->cursor_track, panel_timeline->drag_track_start); + int track_end = qMax(panel_timeline->cursor_track, panel_timeline->drag_track_start); + int track_size = 1 + track_end - track_start; + panel_timeline->split_tracks.resize(track_size); + for (int i=0;isplit_tracks[i] = track_start + i; + } + + if (!alt) { + for (int i=0;idrag_frame_start, panel_timeline->split_tracks[i]); + if (clip_index > -1) { + QVector tracks = panel_timeline->get_tracks_of_linked_clips(clip_index); + for (int j=0;j track_end) { + panel_timeline->split_tracks.append(tracks.at(j)); + } + } + } + } + } + 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()); + long frame_min = qMin(frame_start, frame_end); + long frame_max = qMax(frame_start, frame_end); + + int rsy = panel_timeline->rect_select_y; + if (bottom_align) rsy += height(); + int track_start = getTrackFromScreenPoint(rsy); + int track_end = getTrackFromScreenPoint(event->pos().y()); + int track_min = qMin(track_start, track_end); + int track_max = qMax(track_start, track_end); + + QVector selected_clips; + for (int i=0;iclips.size();i++) { + ClipPtr clip = olive::ActiveSequence->clips.at(i); + if (clip != nullptr && + clip->track >= track_min && + clip->track <= track_max && + !(clip->timeline_in < frame_min && clip->timeline_out < frame_min) && + !(clip->timeline_in > frame_max && clip->timeline_out > frame_max)) { + QVector session_clips; + session_clips.append(clip); + + if (!alt) { + for (int j=0;jlinked.size();j++) { + session_clips.append(olive::ActiveSequence->clips.at(clip->linked.at(j))); + } + } + + for (int j=0;jselections.resize(selected_clips.size() + panel_timeline->selection_offset); + for (int i=0;iselections[i+panel_timeline->selection_offset]; + ClipPtr clip = selected_clips.at(i); + s.old_in = s.in = clip->timeline_in; + s.old_out = s.out = clip->timeline_out; + s.old_track = s.track = clip->track; + } + + panel_timeline->repaint_timeline(); + } else { + panel_timeline->rect_select_x = event->pos().x(); + panel_timeline->rect_select_y = event->pos().y(); + if (bottom_align) panel_timeline->rect_select_y -= height(); + panel_timeline->rect_select_w = 0; + panel_timeline->rect_select_h = 0; + panel_timeline->rect_select_proc = true; + } + } else if (isLiveEditing()) { + // redraw because we have a cursor + panel_timeline->repaint_timeline(); + } else if (panel_timeline->tool == TIMELINE_TOOL_POINTER || + panel_timeline->tool == TIMELINE_TOOL_RIPPLE || + panel_timeline->tool == TIMELINE_TOOL_ROLLING) { + + // hide any tooltip that may be currently showing + QToolTip::hideText(); + + // cache cursor position + QPoint pos = event->pos(); + + // + // check to see if the cursor is on a clip edge + // + + // threshold around a trim point that the cursor can be within and still considered "trimming" + int lim = 5; + 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; + + // used to determine whether the cursor is within the rect of a clip + bool cursor_contains_clip = false; + + // used to determine how close the cursor is to a trim point + // (and more specifically, whether another point is closer or not) + int closeness = INT_MAX; + + // while we loop through the clips, we cache the maximum/minimum tracks in this sequence + int min_track = INT_MAX; + int max_track = INT_MIN; + + // we default to selecting no transition, but set this accordingly if the cursor is on a transition + panel_timeline->transition_select = kTransitionNone; + + // set currently trimming clip to -1 (aka null) + panel_timeline->trim_target = -1; + + // loop through current clips in the sequence + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr) { + + // cache track range + min_track = qMin(min_track, c->track); + max_track = qMax(max_track, c->track); + + // if this clip is on the same track the mouse is + if (c->track == mouse_track) { + + // if this cursor is inside the boundaries of this clip (hovering over the clip) + if (panel_timeline->cursor_frame >= c->timeline_in && + panel_timeline->cursor_frame <= c->timeline_out) { + + // acknowledge that we are hovering over a clip + cursor_contains_clip = true; + + // start a timer to show a tooltip about this clip + tooltip_timer.start(); + tooltip_clip = i; + + // check if the cursor is specifically hovering over one of the clip's transitions + if (c->get_opening_transition() != nullptr + && panel_timeline->cursor_frame <= c->timeline_in + c->get_opening_transition()->get_true_length()) { + + panel_timeline->transition_select = kTransitionOpening; + + } else if (c->get_closing_transition() != nullptr + && panel_timeline->cursor_frame >= c->timeline_out - c->get_closing_transition()->get_true_length()) { + + panel_timeline->transition_select = kTransitionClosing; + + } + } + + // is the cursor hovering around the clip's IN point? + if (c->timeline_in > mouse_frame_lower && c->timeline_in < mouse_frame_upper) { + + // test how close this IN point is to the cursor + int nc = qAbs(c->timeline_in + 1 - panel_timeline->cursor_frame); + + // and test whether it's closer than the last in/out point we found + if (nc < closeness) { + + // 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; + closeness = nc; + found = true; + + } + } + + // is the cursor hovering around the clip's OUT point? + if (c->timeline_out > mouse_frame_lower && c->timeline_out < mouse_frame_upper) { + + // test how close this OUT point is to the cursor + int nc = qAbs(c->timeline_out - 1 - panel_timeline->cursor_frame); + + // and test whether it's closer than the last in/out point we found + if (nc < closeness) { + + // 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; + closeness = nc; + found = true; + + } + } + + // the pointer can be used to resize/trim transitions, here we test if the + // cursor is within the trim point of one of the clip's transitions + if (panel_timeline->tool == TIMELINE_TOOL_POINTER) { + + // if the clip has an opening transition + if (c->get_opening_transition() != nullptr) { + + // cache the timeline frame where the transition ends + long transition_point = c->timeline_in + c->get_opening_transition()->get_true_length(); + + // check if the cursor is hovering around it (within the threshold) + if (transition_point > mouse_frame_lower && transition_point < mouse_frame_upper) { + + // similar to above, test how close it is and if it's closer, make this active + int nc = qAbs(transition_point - 1 - panel_timeline->cursor_frame); + if (nc < closeness) { + panel_timeline->trim_target = i; + panel_timeline->trim_in_point = false; + panel_timeline->transition_select = kTransitionOpening; + closeness = nc; + found = true; + } + } + } + + // if the clip has a closing transition + if (c->get_closing_transition() != nullptr) { + + // cache the timeline frame where the transition starts + long transition_point = c->timeline_out - c->get_closing_transition()->get_true_length(); + + // check if the cursor is hovering around it (within the threshold) + if (transition_point > mouse_frame_lower && transition_point < mouse_frame_upper) { + + // similar to above, test how close it is and if it's closer, make this active + int nc = qAbs(transition_point + 1 - panel_timeline->cursor_frame); + if (nc < closeness) { + panel_timeline->trim_target = i; + panel_timeline->trim_in_point = true; + panel_timeline->transition_select = kTransitionClosing; + closeness = nc; + found = true; + } + } + } + } + } + } + } + + // 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 + setCursor(olive::Cursor_LeftTrim); + } else { // if we're trimming an OUT point + setCursor(olive::Cursor_RightTrim); + } + + } else { + // we didn't find a trim target, so we must be doing something else + // (e.g. dragging a clip or resizing the track heights) + + // 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; + } + } + } + + if (found) { + setCursor(Qt::SizeVerCursor); + } else { + unsetCursor(); + } + } + } else if (panel_timeline->tool == TIMELINE_TOOL_SLIP) { + if (getClipIndexFromCoords(panel_timeline->cursor_frame, panel_timeline->cursor_track) > -1) { + setCursor(Qt::SizeHorCursor); + } else { + unsetCursor(); + } + } else if (panel_timeline->tool == TIMELINE_TOOL_TRANSITION) { + if (panel_timeline->transition_tool_init) { + if (panel_timeline->transition_tool_proc) { + update_ghosts(event->pos(), event->modifiers() & Qt::ShiftModifier); + } else { + ClipPtr c = olive::ActiveSequence->clips.at(panel_timeline->transition_tool_pre_clip); + + Ghost g; + + g.in = g.old_in = g.out = g.old_out = (panel_timeline->transition_tool_type == kTransitionOpening) ? c->timeline_in : c->timeline_out; + g.track = c->track; + g.clip = panel_timeline->transition_tool_pre_clip; + g.media_stream = panel_timeline->transition_tool_type; + g.trimming = false; + + panel_timeline->ghosts.append(g); + + panel_timeline->transition_tool_proc = true; + } + } else { + int mouse_clip = getClipIndexFromCoords(panel_timeline->cursor_frame, panel_timeline->cursor_track); + if (mouse_clip > -1) { + ClipPtr c = olive::ActiveSequence->clips.at(mouse_clip); + if (same_sign(c->track, panel_timeline->transition_tool_side)) { + panel_timeline->transition_tool_pre_clip = mouse_clip; + long halfway = c->timeline_in + (c->getLength()/2); + long between_range = getFrameFromScreenPoint(panel_timeline->zoom, TRANSITION_BETWEEN_RANGE) + 1; + + if (panel_timeline->cursor_frame > halfway) { + panel_timeline->transition_tool_type = kTransitionClosing; + } else { + panel_timeline->transition_tool_type = kTransitionOpening; + } + + panel_timeline->transition_tool_post_clip = -1; + if (panel_timeline->cursor_frame < c->timeline_in + between_range) { + panel_timeline->transition_tool_post_clip = getClipIndexFromCoords(c->timeline_in-1, c->track); + } else if (panel_timeline->cursor_frame > c->timeline_out - between_range) { + panel_timeline->transition_tool_post_clip = getClipIndexFromCoords(c->timeline_out+1, c->track); + } + } + } else { + panel_timeline->transition_tool_pre_clip = -1; + panel_timeline->transition_tool_post_clip = -1; + } + } + + panel_timeline->repaint_timeline(); + } + } } void TimelineWidget::leaveEvent(QEvent*) { - tooltip_timer.stop(); + tooltip_timer.stop(); } int color_brightness(int r, int g, int b) { - return qRound(0.2126*r + 0.7152*g + 0.0722*b); + return qRound(0.2126*r + 0.7152*g + 0.0722*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) { - int divider = ms->audio_channels*2; - int channel_height = clip_rect.height()/ms->audio_channels; + int divider = ms->audio_channels*2; + int channel_height = clip_rect.height()/ms->audio_channels; - int last_waveform_index = -1; + int last_waveform_index = -1; - for (int i=waveform_start;iclip_in + (double(i)/zoom))/media_length) * ms->audio_preview.size())/divider)*divider; - if (last_waveform_index < 0) last_waveform_index = waveform_index; + for (int i=waveform_start;iclip_in + (double(i)/zoom))/media_length) * ms->audio_preview.size())/divider)*divider; + if (last_waveform_index < 0) last_waveform_index = waveform_index; - if (clip->reverse) { - waveform_index = ms->audio_preview.size() - waveform_index - (ms->audio_channels * 2); - } + if (clip->reverse) { + waveform_index = ms->audio_preview.size() - waveform_index - (ms->audio_channels * 2); + } - for (int j=0;jaudio_channels;j++) { - int mid = (olive::CurrentConfig.rectified_waveforms) ? clip_rect.top()+channel_height*(j+1) : clip_rect.top()+channel_height*j+(channel_height/2); + for (int j=0;jaudio_channels;j++) { + int mid = (olive::CurrentConfig.rectified_waveforms) ? clip_rect.top()+channel_height*(j+1) : clip_rect.top()+channel_height*j+(channel_height/2); - int offset_range_start = last_waveform_index+(j*2); - int offset_range_end = waveform_index+(j*2); + int offset_range_start = last_waveform_index+(j*2); + int offset_range_end = waveform_index+(j*2); - qint8 min = qint8(qRound(double(ms->audio_preview.at(offset_range_start)) / 128.0 * (channel_height/2))); - qint8 max = qint8(qRound(double(ms->audio_preview.at(offset_range_start+1)) / 128.0 * (channel_height/2))); + qint8 min = qint8(qRound(double(ms->audio_preview.at(offset_range_start)) / 128.0 * (channel_height/2))); + qint8 max = qint8(qRound(double(ms->audio_preview.at(offset_range_start+1)) / 128.0 * (channel_height/2))); - if ((offset_range_end + 1) < ms->audio_preview.size()) { + if ((offset_range_end + 1) < ms->audio_preview.size()) { - // for waveform drawings, we get the maximum below 0 and maximum above 0 for this waveform range - for (int k=offset_range_start+2;k<=offset_range_end;k+=2) { - min = qMin(min, qint8(qRound(double(ms->audio_preview.at(k)) / 128.0 * (channel_height/2)))); - max = qMax(max, qint8(qRound(double(ms->audio_preview.at(k+1)) / 128.0 * (channel_height/2)))); - } + // for waveform drawings, we get the maximum below 0 and maximum above 0 for this waveform range + for (int k=offset_range_start+2;k<=offset_range_end;k+=2) { + min = qMin(min, qint8(qRound(double(ms->audio_preview.at(k)) / 128.0 * (channel_height/2)))); + max = qMax(max, qint8(qRound(double(ms->audio_preview.at(k+1)) / 128.0 * (channel_height/2)))); + } - // draw waveforms - if (olive::CurrentConfig.rectified_waveforms) { + // draw waveforms + if (olive::CurrentConfig.rectified_waveforms) { - // rectified waveforms start from the bottom and draw upwards - p->drawLine(clip_rect.left()+i, mid, clip_rect.left()+i, mid - (max - min)); - } else { + // rectified waveforms start from the bottom and draw upwards + p->drawLine(clip_rect.left()+i, mid, clip_rect.left()+i, mid - (max - min)); + } else { - // non-rectified waveforms start from the center and draw outwards - p->drawLine(clip_rect.left()+i, mid+min, clip_rect.left()+i, mid+max); + // non-rectified waveforms start from the center and draw outwards + p->drawLine(clip_rect.left()+i, mid+min, clip_rect.left()+i, mid+max); - } - } - } - last_waveform_index = waveform_index; - } + } + } + } + last_waveform_index = waveform_index; + } } void draw_transition(QPainter& p, ClipPtr c, const QRect& clip_rect, QRect& text_rect, int transition_type) { - TransitionPtr t = (transition_type == kTransitionOpening) ? c->get_opening_transition() : c->get_closing_transition(); - if (t != nullptr) { - QColor transition_color(255, 0, 0, 16); - int transition_width = getScreenPointFromFrame(panel_timeline->zoom, t->get_true_length()); - int transition_height = clip_rect.height(); - int tr_y = clip_rect.y(); - int tr_x = 0; - if (transition_type == kTransitionOpening) { - tr_x = clip_rect.x(); - text_rect.setX(text_rect.x()+transition_width); - } else { - tr_x = clip_rect.right()-transition_width; - text_rect.setWidth(text_rect.width()-transition_width); - } - QRect transition_rect = QRect(tr_x, tr_y, transition_width, transition_height); - p.fillRect(transition_rect, transition_color); - QRect transition_text_rect(transition_rect.x() + olive::timeline::kClipTextPadding, transition_rect.y() + olive::timeline::kClipTextPadding, transition_rect.width() - olive::timeline::kClipTextPadding, transition_rect.height() - olive::timeline::kClipTextPadding); - if (transition_text_rect.width() > MAX_TEXT_WIDTH) { - bool draw_text = true; + TransitionPtr t = (transition_type == kTransitionOpening) ? c->get_opening_transition() : c->get_closing_transition(); + if (t != nullptr) { + QColor transition_color(255, 0, 0, 16); + int transition_width = getScreenPointFromFrame(panel_timeline->zoom, t->get_true_length()); + int transition_height = clip_rect.height(); + int tr_y = clip_rect.y(); + int tr_x = 0; + if (transition_type == kTransitionOpening) { + tr_x = clip_rect.x(); + text_rect.setX(text_rect.x()+transition_width); + } else { + tr_x = clip_rect.right()-transition_width; + text_rect.setWidth(text_rect.width()-transition_width); + } + QRect transition_rect = QRect(tr_x, tr_y, transition_width, transition_height); + p.fillRect(transition_rect, transition_color); + QRect transition_text_rect(transition_rect.x() + olive::timeline::kClipTextPadding, transition_rect.y() + olive::timeline::kClipTextPadding, transition_rect.width() - olive::timeline::kClipTextPadding, transition_rect.height() - olive::timeline::kClipTextPadding); + if (transition_text_rect.width() > MAX_TEXT_WIDTH) { + bool draw_text = true; - p.setPen(QColor(0, 0, 0, 96)); - if (t->secondary_clip == nullptr) { - if (transition_type == kTransitionOpening) { - p.drawLine(transition_rect.bottomLeft(), transition_rect.topRight()); - } else { - p.drawLine(transition_rect.topLeft(), transition_rect.bottomRight()); - } - } else { - if (transition_type == kTransitionOpening) { - p.drawLine(QPoint(transition_rect.left(), transition_rect.center().y()), transition_rect.topRight()); - p.drawLine(QPoint(transition_rect.left(), transition_rect.center().y()), transition_rect.bottomRight()); - draw_text = false; - } else { - p.drawLine(QPoint(transition_rect.right(), transition_rect.center().y()), transition_rect.topLeft()); - p.drawLine(QPoint(transition_rect.right(), transition_rect.center().y()), transition_rect.bottomLeft()); - } - } + p.setPen(QColor(0, 0, 0, 96)); + if (t->secondary_clip == nullptr) { + if (transition_type == kTransitionOpening) { + p.drawLine(transition_rect.bottomLeft(), transition_rect.topRight()); + } else { + p.drawLine(transition_rect.topLeft(), transition_rect.bottomRight()); + } + } else { + if (transition_type == kTransitionOpening) { + p.drawLine(QPoint(transition_rect.left(), transition_rect.center().y()), transition_rect.topRight()); + p.drawLine(QPoint(transition_rect.left(), transition_rect.center().y()), transition_rect.bottomRight()); + draw_text = false; + } else { + p.drawLine(QPoint(transition_rect.right(), transition_rect.center().y()), transition_rect.topLeft()); + p.drawLine(QPoint(transition_rect.right(), transition_rect.center().y()), transition_rect.bottomLeft()); + } + } - if (draw_text) { - p.setPen(Qt::white); - p.drawText(transition_text_rect, 0, t->meta->name, &transition_text_rect); - } - } - p.setPen(Qt::black); - p.drawRect(transition_rect); - } + if (draw_text) { + p.setPen(Qt::white); + p.drawText(transition_text_rect, 0, t->meta->name, &transition_text_rect); + } + } + p.setPen(Qt::black); + p.drawRect(transition_rect); + } } void TimelineWidget::paintEvent(QPaintEvent*) { - // Draw clips - if (olive::ActiveSequence != nullptr) { - QPainter p(this); + // Draw clips + if (olive::ActiveSequence != nullptr) { + QPainter p(this); - // get widget width and height - int video_track_limit = 0; - int audio_track_limit = 0; - for (int i=0;iclips.size();i++) { - ClipPtr clip = olive::ActiveSequence->clips.at(i); - if (clip != nullptr) { - video_track_limit = qMin(video_track_limit, clip->track); - audio_track_limit = qMax(audio_track_limit, clip->track); - } - } + // get widget width and height + int video_track_limit = 0; + int audio_track_limit = 0; + for (int i=0;iclips.size();i++) { + ClipPtr clip = olive::ActiveSequence->clips.at(i); + if (clip != nullptr) { + video_track_limit = qMin(video_track_limit, clip->track); + audio_track_limit = qMax(audio_track_limit, clip->track); + } + } - int panel_height = TRACK_DEFAULT_HEIGHT; - if (bottom_align) { - for (int i=-1;i>=video_track_limit;i--) { - panel_height += panel_timeline->calculate_track_height(i, -1); - } - } else { - for (int i=0;i<=audio_track_limit;i++) { - panel_height += panel_timeline->calculate_track_height(i, -1); - } - } - if (bottom_align) { - scrollBar->setMinimum(qMin(0, - panel_height + height())); - } else { - scrollBar->setMaximum(qMax(0, panel_height - height())); - } + int panel_height = TRACK_DEFAULT_HEIGHT; + if (bottom_align) { + for (int i=-1;i>=video_track_limit;i--) { + panel_height += panel_timeline->calculate_track_height(i, -1); + } + } else { + for (int i=0;i<=audio_track_limit;i++) { + panel_height += panel_timeline->calculate_track_height(i, -1); + } + } + if (bottom_align) { + scrollBar->setMinimum(qMin(0, - panel_height + height())); + } else { + scrollBar->setMaximum(qMax(0, panel_height - height())); + } - 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 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; - if (actual_clip_rect.x() < 0) actual_clip_rect.setX(0); - if (actual_clip_rect.right() > width()) actual_clip_rect.setRight(width()); - if (actual_clip_rect.y() < 0) actual_clip_rect.setY(0); - if (actual_clip_rect.bottom() > height()) actual_clip_rect.setBottom(height()); - p.fillRect(actual_clip_rect, (clip->enabled) ? QColor(clip->color_r, clip->color_g, clip->color_b) : QColor(96, 96, 96)); + 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 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; + if (actual_clip_rect.x() < 0) actual_clip_rect.setX(0); + if (actual_clip_rect.right() > width()) actual_clip_rect.setRight(width()); + if (actual_clip_rect.y() < 0) actual_clip_rect.setY(0); + if (actual_clip_rect.bottom() > height()) actual_clip_rect.setBottom(height()); + p.fillRect(actual_clip_rect, (clip->enabled) ? QColor(clip->color_r, clip->color_g, clip->color_b) : QColor(96, 96, 96)); - int thumb_x = clip_rect.x() + 1; + int thumb_x = clip_rect.x() + 1; - if (clip->media != nullptr && clip->media->get_type() == MEDIA_TYPE_FOOTAGE) { - bool draw_checkerboard = false; - QRect checkerboard_rect(clip_rect); - FootagePtr m = clip->media->to_footage(); - FootageStream* ms = m->get_stream_from_file_index(clip->track < 0, clip->media_stream); - if (ms == nullptr) { - draw_checkerboard = true; - } else if (ms->preview_done) { - // draw top and tail triangles - int triangle_size = olive::timeline::kTrackMinHeight >> 2; - if (!ms->infinite_length && clip_rect.width() > triangle_size) { - p.setPen(Qt::NoPen); - p.setBrush(QColor(80, 80, 80)); - if (clip->clip_in == 0 - && clip_rect.x() + triangle_size > 0 - && clip_rect.y() + triangle_size > 0 - && clip_rect.x() < width() - && clip_rect.y() < height()) { - const QPoint points[3] = { - QPoint(clip_rect.x(), clip_rect.y()), - QPoint(clip_rect.x() + triangle_size, clip_rect.y()), - QPoint(clip_rect.x(), clip_rect.y() + triangle_size) - }; - p.drawPolygon(points, 3); - text_rect.setLeft(text_rect.left() + (triangle_size >> 2)); - } - if (clip->timeline_out - clip->timeline_in + clip->clip_in == clip->getMaximumLength() - && clip_rect.right() - triangle_size < width() - && clip_rect.y() + triangle_size > 0 - && clip_rect.right() > 0 - && clip_rect.y() < height()) { - const QPoint points[3] = { - QPoint(clip_rect.right(), clip_rect.y()), - QPoint(clip_rect.right() - triangle_size, clip_rect.y()), - QPoint(clip_rect.right(), clip_rect.y() + triangle_size) - }; - p.drawPolygon(points, 3); - text_rect.setRight(text_rect.right() - (triangle_size >> 2)); - } - } + if (clip->media != nullptr && clip->media->get_type() == MEDIA_TYPE_FOOTAGE) { + bool draw_checkerboard = false; + QRect checkerboard_rect(clip_rect); + FootagePtr m = clip->media->to_footage(); + FootageStream* ms = m->get_stream_from_file_index(clip->track < 0, clip->media_stream); + if (ms == nullptr) { + draw_checkerboard = true; + } else if (ms->preview_done) { + // draw top and tail triangles + int triangle_size = olive::timeline::kTrackMinHeight >> 2; + if (!ms->infinite_length && clip_rect.width() > triangle_size) { + p.setPen(Qt::NoPen); + p.setBrush(QColor(80, 80, 80)); + if (clip->clip_in == 0 + && clip_rect.x() + triangle_size > 0 + && clip_rect.y() + triangle_size > 0 + && clip_rect.x() < width() + && clip_rect.y() < height()) { + const QPoint points[3] = { + QPoint(clip_rect.x(), clip_rect.y()), + QPoint(clip_rect.x() + triangle_size, clip_rect.y()), + QPoint(clip_rect.x(), clip_rect.y() + triangle_size) + }; + p.drawPolygon(points, 3); + text_rect.setLeft(text_rect.left() + (triangle_size >> 2)); + } + if (clip->timeline_out - clip->timeline_in + clip->clip_in == clip->getMaximumLength() + && clip_rect.right() - triangle_size < width() + && clip_rect.y() + triangle_size > 0 + && clip_rect.right() > 0 + && clip_rect.y() < height()) { + const QPoint points[3] = { + QPoint(clip_rect.right(), clip_rect.y()), + QPoint(clip_rect.right() - triangle_size, clip_rect.y()), + QPoint(clip_rect.right(), clip_rect.y() + triangle_size) + }; + p.drawPolygon(points, 3); + text_rect.setRight(text_rect.right() - (triangle_size >> 2)); + } + } - p.setBrush(Qt::NoBrush); + p.setBrush(Qt::NoBrush); - // draw thumbnail/waveform - long media_length = clip->getMaximumLength(); + // draw thumbnail/waveform + long media_length = clip->getMaximumLength(); - if (clip->track < 0) { - // draw thumbnail - int thumb_y = p.fontMetrics().height()+olive::timeline::kClipTextPadding+olive::timeline::kClipTextPadding; - if (thumb_x < width() && thumb_y < height()) { - int space_for_thumb = clip_rect.width()-1; - if (clip->get_opening_transition() != nullptr) { - int ot_width = getScreenPointFromFrame(panel_timeline->zoom, clip->get_opening_transition()->get_true_length()); - thumb_x += ot_width; - space_for_thumb -= ot_width; - } - if (clip->get_closing_transition() != nullptr) { - space_for_thumb -= getScreenPointFromFrame(panel_timeline->zoom, clip->get_closing_transition()->get_true_length()); - } - int thumb_height = clip_rect.height()-thumb_y; - int thumb_width = qRound(thumb_height*(double(ms->video_preview.width())/double(ms->video_preview.height()))); - if (thumb_x + thumb_width >= 0 - && thumb_height > thumb_y - && thumb_y + thumb_height >= 0 - && space_for_thumb > MAX_TEXT_WIDTH) { - int thumb_clip_width = qMin(thumb_width, space_for_thumb); - p.drawImage(QRect(thumb_x, - clip_rect.y()+thumb_y, - thumb_clip_width, - thumb_height), - ms->video_preview, - QRect(0, - 0, - qRound(thumb_clip_width*(double(ms->video_preview.width())/double(thumb_width))), - ms->video_preview.height() - ) - ); - } - } - if (clip->timeline_out - clip->timeline_in + clip->clip_in > clip->getMaximumLength()) { - draw_checkerboard = true; - checkerboard_rect.setLeft(panel_timeline->getTimelineScreenPointFromFrame(clip->getMaximumLength() + clip->timeline_in - clip->clip_in)); - } - } else if (clip_rect.height() > olive::timeline::kTrackMinHeight) { - // draw waveform - p.setPen(QColor(80, 80, 80)); + if (clip->track < 0) { + // draw thumbnail + int thumb_y = p.fontMetrics().height()+olive::timeline::kClipTextPadding+olive::timeline::kClipTextPadding; + if (thumb_x < width() && thumb_y < height()) { + int space_for_thumb = clip_rect.width()-1; + if (clip->get_opening_transition() != nullptr) { + int ot_width = getScreenPointFromFrame(panel_timeline->zoom, clip->get_opening_transition()->get_true_length()); + thumb_x += ot_width; + space_for_thumb -= ot_width; + } + if (clip->get_closing_transition() != nullptr) { + space_for_thumb -= getScreenPointFromFrame(panel_timeline->zoom, clip->get_closing_transition()->get_true_length()); + } + int thumb_height = clip_rect.height()-thumb_y; + int thumb_width = qRound(thumb_height*(double(ms->video_preview.width())/double(ms->video_preview.height()))); + if (thumb_x + thumb_width >= 0 + && thumb_height > thumb_y + && thumb_y + thumb_height >= 0 + && space_for_thumb > MAX_TEXT_WIDTH) { + int thumb_clip_width = qMin(thumb_width, space_for_thumb); + p.drawImage(QRect(thumb_x, + clip_rect.y()+thumb_y, + thumb_clip_width, + thumb_height), + ms->video_preview, + QRect(0, + 0, + qRound(thumb_clip_width*(double(ms->video_preview.width())/double(thumb_width))), + ms->video_preview.height() + ) + ); + } + } + if (clip->timeline_out - clip->timeline_in + clip->clip_in > clip->getMaximumLength()) { + draw_checkerboard = true; + checkerboard_rect.setLeft(panel_timeline->getTimelineScreenPointFromFrame(clip->getMaximumLength() + clip->timeline_in - clip->clip_in)); + } + } else if (clip_rect.height() > olive::timeline::kTrackMinHeight) { + // draw waveform + p.setPen(QColor(80, 80, 80)); - int waveform_start = -qMin(clip_rect.x(), 0); - int waveform_limit = qMin(clip_rect.width(), getScreenPointFromFrame(panel_timeline->zoom, media_length - clip->clip_in)); + int waveform_start = -qMin(clip_rect.x(), 0); + int waveform_limit = qMin(clip_rect.width(), getScreenPointFromFrame(panel_timeline->zoom, media_length - clip->clip_in)); - if ((clip_rect.x() + waveform_limit) > width()) { - waveform_limit -= (clip_rect.x() + waveform_limit - width()); - } else if (waveform_limit < clip_rect.width()) { - draw_checkerboard = true; - if (waveform_limit > 0) checkerboard_rect.setLeft(checkerboard_rect.left() + waveform_limit); - } + if ((clip_rect.x() + waveform_limit) > width()) { + waveform_limit -= (clip_rect.x() + waveform_limit - width()); + } else if (waveform_limit < clip_rect.width()) { + draw_checkerboard = true; + if (waveform_limit > 0) checkerboard_rect.setLeft(checkerboard_rect.left() + waveform_limit); + } - draw_waveform(clip, ms, media_length, &p, clip_rect, waveform_start, waveform_limit, panel_timeline->zoom); - } - } - if (draw_checkerboard) { - checkerboard_rect.setLeft(qMax(checkerboard_rect.left(), 0)); - checkerboard_rect.setRight(qMin(checkerboard_rect.right(), width())); - checkerboard_rect.setTop(qMax(checkerboard_rect.top(), 0)); - checkerboard_rect.setBottom(qMin(checkerboard_rect.bottom(), height())); + draw_waveform(clip, ms, media_length, &p, clip_rect, waveform_start, waveform_limit, panel_timeline->zoom); + } + } + if (draw_checkerboard) { + checkerboard_rect.setLeft(qMax(checkerboard_rect.left(), 0)); + checkerboard_rect.setRight(qMin(checkerboard_rect.right(), width())); + checkerboard_rect.setTop(qMax(checkerboard_rect.top(), 0)); + checkerboard_rect.setBottom(qMin(checkerboard_rect.bottom(), height())); - if (checkerboard_rect.left() < width() - && checkerboard_rect.right() >= 0 - && checkerboard_rect.top() < height() - && checkerboard_rect.bottom() >= 0) { - // draw "error lines" if media stream is missing - p.setPen(QPen(QColor(64, 64, 64), 2)); - int limit = checkerboard_rect.width(); - int clip_height = checkerboard_rect.height(); - for (int j=-clip_height;j checkerboard_rect.right()) { - lines_end_y -= (checkerboard_rect.right() - lines_end_x); - lines_end_x = checkerboard_rect.right(); - } - p.drawLine(lines_start_x, lines_start_y, lines_end_x, lines_end_y); - } - } - } - } + if (checkerboard_rect.left() < width() + && checkerboard_rect.right() >= 0 + && checkerboard_rect.top() < height() + && checkerboard_rect.bottom() >= 0) { + // draw "error lines" if media stream is missing + p.setPen(QPen(QColor(64, 64, 64), 2)); + int limit = checkerboard_rect.width(); + int clip_height = checkerboard_rect.height(); + for (int j=-clip_height;j checkerboard_rect.right()) { + lines_end_y -= (checkerboard_rect.right() - lines_end_x); + lines_end_x = checkerboard_rect.right(); + } + p.drawLine(lines_start_x, lines_start_y, lines_end_x, lines_end_y); + } + } + } + } - // draw clip markers - for (int j=0;jget_markers().size();j++) { - const Marker& m = clip->get_markers().at(j); + // draw clip markers + for (int j=0;jget_markers().size();j++) { + const Marker& m = clip->get_markers().at(j); - // convert marker time (in clip time) to sequence time - long marker_time = m.frame + clip->timeline_in - clip->clip_in; - int marker_x = panel_timeline->getTimelineScreenPointFromFrame(marker_time); - if (marker_x > clip_rect.x() && marker_x < clip_rect.right()) { - draw_marker(p, marker_x, clip_rect.bottom()-p.fontMetrics().height(), clip_rect.bottom(), false); - } - } - p.setBrush(Qt::NoBrush); + // convert marker time (in clip time) to sequence time + long marker_time = m.frame + clip->timeline_in - clip->clip_in; + int marker_x = panel_timeline->getTimelineScreenPointFromFrame(marker_time); + if (marker_x > clip_rect.x() && marker_x < clip_rect.right()) { + draw_marker(p, marker_x, clip_rect.bottom()-p.fontMetrics().height(), clip_rect.bottom(), false); + } + } + p.setBrush(Qt::NoBrush); - // draw clip transitions - draw_transition(p, clip, clip_rect, text_rect, kTransitionOpening); - draw_transition(p, clip, clip_rect, text_rect, kTransitionClosing); + // draw clip transitions + draw_transition(p, clip, clip_rect, text_rect, kTransitionOpening); + draw_transition(p, clip, clip_rect, text_rect, kTransitionClosing); - // top left bevel - p.setPen(Qt::white); - if (clip_rect.x() >= 0 && clip_rect.x() < width()) p.drawLine(clip_rect.bottomLeft(), clip_rect.topLeft()); - if (clip_rect.y() >= 0 && clip_rect.y() < height()) p.drawLine(QPoint(qMax(0, clip_rect.left()), clip_rect.top()), QPoint(qMin(width(), clip_rect.right()), clip_rect.top())); + // top left bevel + p.setPen(Qt::white); + if (clip_rect.x() >= 0 && clip_rect.x() < width()) p.drawLine(clip_rect.bottomLeft(), clip_rect.topLeft()); + if (clip_rect.y() >= 0 && clip_rect.y() < height()) p.drawLine(QPoint(qMax(0, clip_rect.left()), clip_rect.top()), QPoint(qMin(width(), clip_rect.right()), clip_rect.top())); - // draw text - if (text_rect.width() > MAX_TEXT_WIDTH && text_rect.right() > 0 && text_rect.left() < width()) { - if (!clip->enabled) { - p.setPen(Qt::gray); - } else if (color_brightness(clip->color_r, clip->color_g, clip->color_b) > 160) { - // set to black if color is bright - p.setPen(Qt::black); - } - if (clip->linked.size() > 0) { - int underline_y = olive::timeline::kClipTextPadding + p.fontMetrics().height() + clip_rect.top(); - int underline_width = qMin(text_rect.width() - 1, p.fontMetrics().width(clip->name)); - p.drawLine(text_rect.x(), underline_y, text_rect.x() + underline_width, underline_y); - } - QString name = clip->name; - if (clip->speed != 1.0 || clip->reverse) { - name += " ("; - if (clip->reverse) name += "-"; - name += QString::number(clip->speed*100) + "%)"; - } - p.drawText(text_rect, 0, name, &text_rect); - } + // draw text + if (text_rect.width() > MAX_TEXT_WIDTH && text_rect.right() > 0 && text_rect.left() < width()) { + if (!clip->enabled) { + p.setPen(Qt::gray); + } else if (color_brightness(clip->color_r, clip->color_g, clip->color_b) > 160) { + // set to black if color is bright + p.setPen(Qt::black); + } + if (clip->linked.size() > 0) { + int underline_y = olive::timeline::kClipTextPadding + p.fontMetrics().height() + clip_rect.top(); + int underline_width = qMin(text_rect.width() - 1, p.fontMetrics().width(clip->name)); + p.drawLine(text_rect.x(), underline_y, text_rect.x() + underline_width, underline_y); + } + QString name = clip->name; + if (clip->speed != 1.0 || clip->reverse) { + name += " ("; + if (clip->reverse) name += "-"; + name += QString::number(clip->speed*100) + "%)"; + } + p.drawText(text_rect, 0, name, &text_rect); + } - // bottom right gray - p.setPen(QColor(0, 0, 0, 128)); - if (clip_rect.right() >= 0 && clip_rect.right() < width()) p.drawLine(clip_rect.bottomRight(), clip_rect.topRight()); - if (clip_rect.bottom() >= 0 && clip_rect.bottom() < height()) p.drawLine(QPoint(qMax(0, clip_rect.left()), clip_rect.bottom()), QPoint(qMin(width(), clip_rect.right()), clip_rect.bottom())); + // bottom right gray + p.setPen(QColor(0, 0, 0, 128)); + if (clip_rect.right() >= 0 && clip_rect.right() < width()) p.drawLine(clip_rect.bottomRight(), clip_rect.topRight()); + if (clip_rect.bottom() >= 0 && clip_rect.bottom() < height()) p.drawLine(QPoint(qMax(0, clip_rect.left()), clip_rect.bottom()), QPoint(qMin(width(), clip_rect.right()), clip_rect.bottom())); - // draw transition tool - if (panel_timeline->tool == TIMELINE_TOOL_TRANSITION && (panel_timeline->transition_tool_pre_clip == i || panel_timeline->transition_tool_post_clip == i)) { - int type = panel_timeline->transition_tool_type; - if (panel_timeline->transition_tool_post_clip == i) { - // invert transition type - type = (type == kTransitionClosing) ? kTransitionOpening : kTransitionClosing; - } - QRect transition_tool_rect = clip_rect; - if (type == kTransitionClosing) { - if (panel_timeline->transition_tool_post_clip > -1) { - transition_tool_rect.setLeft(transition_tool_rect.right() - TRANSITION_BETWEEN_RANGE); - } else { - transition_tool_rect.setLeft(transition_tool_rect.left() + (3*(transition_tool_rect.width()>>2))); - } - } else { - if (panel_timeline->transition_tool_post_clip > -1) { - transition_tool_rect.setWidth(TRANSITION_BETWEEN_RANGE); - } else { - transition_tool_rect.setWidth(transition_tool_rect.width()>>2); - } - } - if (transition_tool_rect.left() < width() && transition_tool_rect.right() > 0) { - if (transition_tool_rect.left() < 0) { - transition_tool_rect.setLeft(0); - } - if (transition_tool_rect.right() > width()) { - transition_tool_rect.setRight(width()); - } - p.fillRect(transition_tool_rect, QColor(0, 0, 0, 128)); - } - } - } - } - } + // draw transition tool + if (panel_timeline->tool == TIMELINE_TOOL_TRANSITION && (panel_timeline->transition_tool_pre_clip == i || panel_timeline->transition_tool_post_clip == i)) { + int type = panel_timeline->transition_tool_type; + if (panel_timeline->transition_tool_post_clip == i) { + // invert transition type + type = (type == kTransitionClosing) ? kTransitionOpening : kTransitionClosing; + } + QRect transition_tool_rect = clip_rect; + if (type == kTransitionClosing) { + if (panel_timeline->transition_tool_post_clip > -1) { + transition_tool_rect.setLeft(transition_tool_rect.right() - TRANSITION_BETWEEN_RANGE); + } else { + transition_tool_rect.setLeft(transition_tool_rect.left() + (3*(transition_tool_rect.width()>>2))); + } + } else { + if (panel_timeline->transition_tool_post_clip > -1) { + transition_tool_rect.setWidth(TRANSITION_BETWEEN_RANGE); + } else { + transition_tool_rect.setWidth(transition_tool_rect.width()>>2); + } + } + if (transition_tool_rect.left() < width() && transition_tool_rect.right() > 0) { + if (transition_tool_rect.left() < 0) { + transition_tool_rect.setLeft(0); + } + if (transition_tool_rect.right() > width()) { + transition_tool_rect.setRight(width()); + } + p.fillRect(transition_tool_rect, QColor(0, 0, 0, 128)); + } + } + } + } + } - // Draw recording clip if recording if valid - 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); - if (panel_sequence_viewer->recording_start != panel_sequence_viewer->recording_end) { - QRect rec_rect( - rec_track_x, - rec_track_y, - getScreenPointFromFrame(panel_timeline->zoom, panel_sequence_viewer->recording_end - panel_sequence_viewer->recording_start), - rec_track_height - ); - p.setPen(QPen(QColor(96, 96, 96), 2)); - p.fillRect(rec_rect, QColor(192, 192, 192)); - p.drawRect(rec_rect); - } - QRect active_rec_rect( - rec_track_x, - rec_track_y, - getScreenPointFromFrame(panel_timeline->zoom, panel_sequence_viewer->seq->playhead - panel_sequence_viewer->recording_start), - rec_track_height - ); - p.setPen(QPen(QColor(192, 0, 0), 2)); - p.fillRect(active_rec_rect, QColor(255, 96, 96)); - p.drawRect(active_rec_rect); + // Draw recording clip if recording if valid + 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); + if (panel_sequence_viewer->recording_start != panel_sequence_viewer->recording_end) { + QRect rec_rect( + rec_track_x, + rec_track_y, + getScreenPointFromFrame(panel_timeline->zoom, panel_sequence_viewer->recording_end - panel_sequence_viewer->recording_start), + rec_track_height + ); + p.setPen(QPen(QColor(96, 96, 96), 2)); + p.fillRect(rec_rect, QColor(192, 192, 192)); + p.drawRect(rec_rect); + } + QRect active_rec_rect( + rec_track_x, + rec_track_y, + getScreenPointFromFrame(panel_timeline->zoom, panel_sequence_viewer->seq->playhead - panel_sequence_viewer->recording_start), + rec_track_height + ); + p.setPen(QPen(QColor(192, 0, 0), 2)); + p.fillRect(active_rec_rect, QColor(255, 96, 96)); + p.drawRect(active_rec_rect); - p.setPen(Qt::NoPen); + p.setPen(Qt::NoPen); - if (!panel_sequence_viewer->playing) { - int rec_marker_size = 6; - int rec_track_midY = rec_track_y + (rec_track_height >> 1); - p.setBrush(Qt::white); - QPoint cue_marker[3] = { - QPoint(rec_track_x, rec_track_midY - rec_marker_size), - QPoint(rec_track_x + rec_marker_size, rec_track_midY), - QPoint(rec_track_x, rec_track_midY + rec_marker_size) - }; - p.drawPolygon(cue_marker, 3); - } - } + if (!panel_sequence_viewer->playing) { + int rec_marker_size = 6; + int rec_track_midY = rec_track_y + (rec_track_height >> 1); + p.setBrush(Qt::white); + QPoint cue_marker[3] = { + QPoint(rec_track_x, rec_track_midY - rec_marker_size), + QPoint(rec_track_x + rec_marker_size, rec_track_midY), + QPoint(rec_track_x, rec_track_midY + rec_marker_size) + }; + p.drawPolygon(cue_marker, 3); + } + } - // Draw track lines - if (olive::CurrentConfig.show_track_lines) { - p.setPen(QColor(0, 0, 0, 96)); - audio_track_limit++; - if (video_track_limit == 0) video_track_limit--; + // Draw track lines + if (olive::CurrentConfig.show_track_lines) { + p.setPen(QColor(0, 0, 0, 96)); + audio_track_limit++; + if (video_track_limit == 0) video_track_limit--; - if (bottom_align) { - // only draw lines for video tracks - for (int i=video_track_limit;i<0;i++) { - int line_y = getScreenPointFromTrack(i) - 1; - p.drawLine(0, line_y, rect().width(), line_y); - } - } else { - // only draw lines for audio tracks - for (int i=0;icalculate_track_height(i, -1); - p.drawLine(0, line_y, rect().width(), line_y); - } - } - } + if (bottom_align) { + // only draw lines for video tracks + for (int i=video_track_limit;i<0;i++) { + int line_y = getScreenPointFromTrack(i) - 1; + p.drawLine(0, line_y, rect().width(), line_y); + } + } else { + // only draw lines for audio tracks + for (int i=0;icalculate_track_height(i, -1); + p.drawLine(0, line_y, rect().width(), line_y); + } + } + } - // Draw selections - for (int i=0;iselections.size();i++) { - const Selection& s = olive::ActiveSequence->selections.at(i); - if (is_track_visible(s.track)) { - int selection_y = getScreenPointFromTrack(s.track); - 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)); - } - } + // Draw selections + for (int i=0;iselections.size();i++) { + const Selection& s = olive::ActiveSequence->selections.at(i); + if (is_track_visible(s.track)) { + int selection_y = getScreenPointFromTrack(s.track); + 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)); + } + } - // draw rectangle select - if (panel_timeline->rect_select_proc) { - int rsy = panel_timeline->rect_select_y; - int rsh = panel_timeline->rect_select_h; - if (bottom_align) { - rsy += height(); - } - QRect rect_select(panel_timeline->rect_select_x, rsy, panel_timeline->rect_select_w, rsh); - draw_selection_rectangle(p, rect_select); - } + // draw rectangle select + if (panel_timeline->rect_select_proc) { + int rsy = panel_timeline->rect_select_y; + int rsh = panel_timeline->rect_select_h; + if (bottom_align) { + rsy += height(); + } + QRect rect_select(panel_timeline->rect_select_x, rsy, panel_timeline->rect_select_w, rsh); + draw_selection_rectangle(p, rect_select); + } - // Draw ghosts - if (!panel_timeline->ghosts.isEmpty()) { - QVector insert_points; - long first_ghost = LONG_MAX; - for (int i=0;ighosts.size();i++) { - const Ghost& g = panel_timeline->ghosts.at(i); - first_ghost = qMin(first_ghost, g.in); - if (is_track_visible(g.track)) { - 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; + // Draw ghosts + if (!panel_timeline->ghosts.isEmpty()) { + QVector insert_points; + long first_ghost = LONG_MAX; + for (int i=0;ighosts.size();i++) { + const Ghost& g = panel_timeline->ghosts.at(i); + first_ghost = qMin(first_ghost, g.in); + if (is_track_visible(g.track)) { + 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; - insert_points.append(ghost_y + (ghost_height>>1)); + insert_points.append(ghost_y + (ghost_height>>1)); - p.setPen(QColor(255, 255, 0)); - for (int j=0;jmove_insert && !insert_points.isEmpty()) { - p.setBrush(Qt::white); - p.setPen(Qt::NoPen); - int insert_x = panel_timeline->getTimelineScreenPointFromFrame(first_ghost); - int tri_size = olive::timeline::kTrackMinHeight>>2; + // draw insert indicator + if (panel_timeline->move_insert && !insert_points.isEmpty()) { + p.setBrush(Qt::white); + p.setPen(Qt::NoPen); + int insert_x = panel_timeline->getTimelineScreenPointFromFrame(first_ghost); + int tri_size = olive::timeline::kTrackMinHeight>>2; - for (int i=0;isplitting) { - for (int i=0;isplit_tracks.size();i++) { - if (is_track_visible(panel_timeline->split_tracks.at(i))) { - int cursor_x = panel_timeline->getTimelineScreenPointFromFrame(panel_timeline->drag_frame_start); - int cursor_y = getScreenPointFromTrack(panel_timeline->split_tracks.at(i)); + // Draw splitting cursor + if (panel_timeline->splitting) { + for (int i=0;isplit_tracks.size();i++) { + if (is_track_visible(panel_timeline->split_tracks.at(i))) { + int cursor_x = panel_timeline->getTimelineScreenPointFromFrame(panel_timeline->drag_frame_start); + 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.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)); + } + } + } - // Draw playhead - p.setPen(Qt::red); - int playhead_x = panel_timeline->getTimelineScreenPointFromFrame(olive::ActiveSequence->playhead); - p.drawLine(playhead_x, rect().top(), playhead_x, rect().bottom()); + // Draw playhead + p.setPen(Qt::red); + int playhead_x = panel_timeline->getTimelineScreenPointFromFrame(olive::ActiveSequence->playhead); + p.drawLine(playhead_x, rect().top(), playhead_x, rect().bottom()); - // draw border - p.setPen(QColor(0, 0, 0, 64)); - int edge_y = (bottom_align) ? rect().height()-1 : 0; - p.drawLine(0, edge_y, rect().width(), edge_y); + // draw border + p.setPen(QColor(0, 0, 0, 64)); + int edge_y = (bottom_align) ? rect().height()-1 : 0; + p.drawLine(0, edge_y, rect().width(), edge_y); - // draw snap point - if (panel_timeline->snapped) { - p.setPen(Qt::white); - int snap_x = panel_timeline->getTimelineScreenPointFromFrame(panel_timeline->snap_point); - p.drawLine(snap_x, 0, snap_x, height()); - } + // draw snap point + if (panel_timeline->snapped) { + p.setPen(Qt::white); + int snap_x = panel_timeline->getTimelineScreenPointFromFrame(panel_timeline->snap_point); + p.drawLine(snap_x, 0, snap_x, height()); + } - // Draw edit cursor - if (isLiveEditing() && 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); + // Draw edit cursor + if (isLiveEditing() && 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.setPen(Qt::gray); + p.drawLine(cursor_x, cursor_y, cursor_x, cursor_y + panel_timeline->calculate_track_height(panel_timeline->cursor_track, -1)); + } + } } void TimelineWidget::resizeEvent(QResizeEvent *) { - scrollBar->setPageStep(height()); + scrollBar->setPageStep(height()); } bool TimelineWidget::is_track_visible(int track) { - return (bottom_align == (track < 0)); + return (bottom_align == (track < 0)); } // ************************************** @@ -2827,55 +2827,55 @@ bool TimelineWidget::is_track_visible(int track) { // ************************************** int TimelineWidget::getTrackFromScreenPoint(int y) { - y += scroll; - if (bottom_align) { - y = -(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++; - } else { - counter--; - } - track_height = panel_timeline->calculate_track_height(counter, -1); - } - return counter; + y += scroll; + if (bottom_align) { + y = -(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++; + } else { + counter--; + } + 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++; - } - y++; - return (bottom_align) ? height() - y - scroll : y - scroll; + 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++; + } + y++; + return (bottom_align) ? height() - y - scroll : y - scroll; } int TimelineWidget::getClipIndexFromCoords(long frame, int track) { - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr && c->track == track && frame >= c->timeline_in && frame < c->timeline_out) { - return i; - } - } - return -1; + for (int i=0;iclips.size();i++) { + ClipPtr c = olive::ActiveSequence->clips.at(i); + if (c != nullptr && c->track == track && frame >= c->timeline_in && frame < c->timeline_out) { + return i; + } + } + return -1; } void TimelineWidget::setScroll(int s) { - scroll = s; - update(); + scroll = s; + update(); } void TimelineWidget::reveal_media() { - panel_project->reveal_media(rc_reveal_media); + panel_project->reveal_media(rc_reveal_media); }