diff --git a/app/dialog/preferences/tabs/preferencesgeneraltab.cpp b/app/dialog/preferences/tabs/preferencesgeneraltab.cpp index e46959475..520728c36 100644 --- a/app/dialog/preferences/tabs/preferencesgeneraltab.cpp +++ b/app/dialog/preferences/tabs/preferencesgeneraltab.cpp @@ -48,9 +48,6 @@ PreferencesGeneralTab::PreferencesGeneralTab() // Add default language (en-US) language_combobox_->addItem(QLocale("en_US").nativeLanguageName()); - // Set sequence to pick up default parameters from the config - default_sequence_.set_default_parameters(); - /* // add languages from file QList translation_paths = get_language_paths(); @@ -106,29 +103,15 @@ PreferencesGeneralTab::PreferencesGeneralTab() default_still_length_ = new FloatSlider(); default_still_length_->SetMinimum(0.1); + default_still_length_->SetFormat(tr("%1 seconds")); default_still_length_->SetValue(Config::Current()["DefaultStillLength"].value().toDouble()); general_layout->addWidget(default_still_length_); - row++; - - general_layout->addWidget(new QLabel(tr("Default Sequence Settings:")), row, 0); - - // General -> Default Sequence Settings - QPushButton* default_sequence_settings = new QPushButton(tr("Edit")); - connect(default_sequence_settings, SIGNAL(clicked(bool)), this, SLOT(edit_default_sequence_settings())); - general_layout->addWidget(default_sequence_settings, row, 1); - layout->addStretch(); } void PreferencesGeneralTab::Accept() { - Config::Current()["DefaultSequenceWidth"] = default_sequence_.video_params().width(); - Config::Current()["DefaultSequenceHeight"] = default_sequence_.video_params().height();; - Config::Current()["DefaultSequenceFrameRate"] = QVariant::fromValue(default_sequence_.video_params().time_base()); - Config::Current()["DefaultSequenceAudioFrequency"] = default_sequence_.audio_params().sample_rate(); - Config::Current()["DefaultSequenceAudioLayout"] = QVariant::fromValue(default_sequence_.audio_params().channel_layout()); - Config::Current()["RectifiedWaveforms"] = rectified_waveforms_->isChecked(); Config::Current()["Autoscroll"] = autoscroll_method_->currentData(); @@ -136,12 +119,4 @@ void PreferencesGeneralTab::Accept() Config::Current()["DefaultStillLength"] = QVariant::fromValue(rational::fromDouble(default_still_length_->GetValue())); } -void PreferencesGeneralTab::edit_default_sequence_settings() -{ - SequenceDialog sd(&default_sequence_, SequenceDialog::kExisting, this); - sd.SetUndoable(false); - sd.SetNameIsEditable(false); - sd.exec(); -} - OLIVE_NAMESPACE_EXIT diff --git a/app/dialog/preferences/tabs/preferencesgeneraltab.h b/app/dialog/preferences/tabs/preferencesgeneraltab.h index 54a712597..609d182c9 100644 --- a/app/dialog/preferences/tabs/preferencesgeneraltab.h +++ b/app/dialog/preferences/tabs/preferencesgeneraltab.h @@ -39,12 +39,6 @@ public: virtual void Accept() override; -private slots: - /** - * @brief Shows a NewSequenceDialog attached to default_sequence - */ - void edit_default_sequence_settings(); - private: QComboBox* language_combobox_; @@ -54,11 +48,6 @@ private: FloatSlider* default_still_length_; - /** - * @brief A sequence we can feed to a SequenceDialog to change the defaults - */ - Sequence default_sequence_; - }; OLIVE_NAMESPACE_EXIT diff --git a/app/dialog/sequence/CMakeLists.txt b/app/dialog/sequence/CMakeLists.txt index 150197b77..39e521400 100644 --- a/app/dialog/sequence/CMakeLists.txt +++ b/app/dialog/sequence/CMakeLists.txt @@ -18,5 +18,10 @@ set(OLIVE_SOURCES ${OLIVE_SOURCES} dialog/sequence/sequence.h dialog/sequence/sequence.cpp + dialog/sequence/sequencedialogparametertab.h + dialog/sequence/sequencedialogparametertab.cpp + dialog/sequence/sequencedialogpresettab.h + dialog/sequence/sequencedialogpresettab.cpp + dialog/sequence/sequencepreset.h PARENT_SCOPE ) diff --git a/app/dialog/sequence/sequence.cpp b/app/dialog/sequence/sequence.cpp index b4b637bbf..21237f1d1 100644 --- a/app/dialog/sequence/sequence.cpp +++ b/app/dialog/sequence/sequence.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "core.h" @@ -41,43 +42,21 @@ SequenceDialog::SequenceDialog(Sequence* s, Type t, QWidget* parent) : { QVBoxLayout* layout = new QVBoxLayout(this); - // Set up preset section - QHBoxLayout* preset_layout = new QHBoxLayout(); - preset_layout->addWidget(new QLabel(tr("Preset:"))); - QComboBox* preset_combobox = new QComboBox(); - preset_layout->addWidget(preset_combobox); - layout->addLayout(preset_layout); + QSplitter* splitter = new QSplitter(); + layout->addWidget(splitter); - // Set up video section - QGroupBox* video_group = new QGroupBox(); - video_group->setTitle(tr("Video")); - QGridLayout* video_layout = new QGridLayout(video_group); - video_layout->addWidget(new QLabel(tr("Width:")), 0, 0); - video_width_field_ = new QSpinBox(); - video_width_field_->setMaximum(99999); - video_layout->addWidget(video_width_field_, 0, 1); - video_layout->addWidget(new QLabel(tr("Height:")), 1, 0); - video_height_field_ = new QSpinBox(); - video_height_field_->setMaximum(99999); - video_layout->addWidget(video_height_field_, 1, 1); - video_layout->addWidget(new QLabel(tr("Frame Rate:")), 2, 0); - video_frame_rate_field_ = new QComboBox(); - video_layout->addWidget(video_frame_rate_field_, 2, 1); - layout->addWidget(video_group); + preset_tab_ = new SequenceDialogPresetTab(); + splitter->addWidget(preset_tab_); - // Set up audio section - QGroupBox* audio_group = new QGroupBox(); - audio_group->setTitle(tr("Audio")); - QGridLayout* audio_layout = new QGridLayout(audio_group); - audio_layout->addWidget(new QLabel(tr("Sample Rate:")), 0, 0); - audio_sample_rate_field_ = new QComboBox(); - // FIXME: No sample rate made - audio_layout->addWidget(audio_sample_rate_field_, 0, 1); - audio_layout->addWidget(new QLabel(tr("Channels:")), 1, 0); - audio_channels_field_ = new QComboBox(); - // FIXME: No channels made - audio_layout->addWidget(audio_channels_field_, 1, 1); - layout->addWidget(audio_group); + parameter_tab_ = new SequenceDialogParameterTab(sequence_); + splitter->addWidget(parameter_tab_); + + connect(preset_tab_, &SequenceDialogPresetTab::PresetChanged, + parameter_tab_, &SequenceDialogParameterTab::PresetChanged); + connect(preset_tab_, &SequenceDialogPresetTab::PresetAccepted, + this, &SequenceDialog::accept); + connect(parameter_tab_, &SequenceDialogParameterTab::SaveParametersAsPreset, + preset_tab_, &SequenceDialogPresetTab::SaveParametersAsPreset); // Set up name section QHBoxLayout* name_layout = new QHBoxLayout(); @@ -103,41 +82,6 @@ SequenceDialog::SequenceDialog(Sequence* s, Type t, QWidget* parent) : break; } - // Set up available frame rates - frame_rate_list_ = Core::SupportedFrameRates(); - foreach (const rational& fr, frame_rate_list_) { - video_frame_rate_field_->addItem(Core::FrameRateToString(fr)); - } - - // Set up available sample rates - sample_rate_list_ = Core::SupportedSampleRates(); - foreach (const int& sr, sample_rate_list_) { - audio_sample_rate_field_->addItem(Core::SampleRateToString(sr)); - } - - // Set up available channel layouts - QList channel_layouts = Core::SupportedChannelLayouts(); - foreach (const uint64_t& ch_layout, channel_layouts) { - audio_channels_field_->addItem(Core::ChannelLayoutToString(ch_layout), QVariant::fromValue(ch_layout)); - } - - // Set values based on input sequence - video_width_field_->setValue(sequence_->video_params().width()); - video_height_field_->setValue(sequence_->video_params().height()); - - int frame_rate_index = frame_rate_list_.indexOf(sequence_->video_params().time_base().flipped()); - video_frame_rate_field_->setCurrentIndex(frame_rate_index); - - int sample_rate_index = sample_rate_list_.indexOf(sequence_->audio_params().sample_rate()); - audio_sample_rate_field_->setCurrentIndex(sample_rate_index); - - for (int i=0;icount();i++) { - if (audio_channels_field_->itemData(i).toULongLong() == sequence_->audio_params().channel_layout()) { - audio_channels_field_->setCurrentIndex(i); - break; - } - } - name_field_->setText(sequence_->name()); } @@ -159,17 +103,17 @@ void SequenceDialog::accept() } // Get the rational at the combobox's index (which will be correct provided AddFrameRate() was used at all time) - rational video_time_base = frame_rate_list_.at(video_frame_rate_field_->currentIndex()).flipped(); + rational video_time_base = parameter_tab_->GetSelectedVideoFrameRate().flipped(); // Get the rational at the combobox's index (which will be correct provided AddFrameRate() was used at all time) - int audio_sample_rate = sample_rate_list_.at(audio_sample_rate_field_->currentIndex()); + int audio_sample_rate = parameter_tab_->GetSelectedAudioSampleRate(); // Get the audio channel layout value - uint64_t channels = audio_channels_field_->currentData().toULongLong(); + uint64_t channels = parameter_tab_->GetSelectedAudioChannelLayout(); // Generate video and audio parameter structs from data - VideoParams video_params = VideoParams(video_width_field_->value(), - video_height_field_->value(), + VideoParams video_params = VideoParams(parameter_tab_->GetSelectedVideoWidth(), + parameter_tab_->GetSelectedVideoHeight(), video_time_base); AudioParams audio_params = AudioParams(audio_sample_rate, diff --git a/app/dialog/sequence/sequence.h b/app/dialog/sequence/sequence.h index 228b87a13..acbe22a0b 100644 --- a/app/dialog/sequence/sequence.h +++ b/app/dialog/sequence/sequence.h @@ -26,6 +26,8 @@ #include #include "project/item/sequence/sequence.h" +#include "sequencedialogparametertab.h" +#include "sequencedialogpresettab.h" #include "undo/undocommand.h" OLIVE_NAMESPACE_ENTER @@ -93,24 +95,14 @@ public slots: private: Sequence* sequence_; + SequenceDialogPresetTab* preset_tab_; + + SequenceDialogParameterTab* parameter_tab_; + bool make_undoable_; - QSpinBox* video_width_field_; - - QSpinBox* video_height_field_; - - QComboBox* video_frame_rate_field_; - - QComboBox* audio_sample_rate_field_; - - QComboBox* audio_channels_field_; - QLineEdit* name_field_; - QList frame_rate_list_; - - QList sample_rate_list_; - /** * @brief A QUndoCommand for setting the parameters on a sequence */ diff --git a/app/dialog/sequence/sequencedialogparametertab.cpp b/app/dialog/sequence/sequencedialogparametertab.cpp new file mode 100644 index 000000000..8d5370141 --- /dev/null +++ b/app/dialog/sequence/sequencedialogparametertab.cpp @@ -0,0 +1,134 @@ +#include "sequencedialogparametertab.h" + +#include +#include +#include +#include + +#include "core.h" + +OLIVE_NAMESPACE_ENTER + +SequenceDialogParameterTab::SequenceDialogParameterTab(Sequence* sequence, QWidget* parent) : + QWidget(parent) +{ + QVBoxLayout* layout = new QVBoxLayout(this); + + // Set up video section + QGroupBox* video_group = new QGroupBox(); + video_group->setTitle(tr("Video")); + QGridLayout* video_layout = new QGridLayout(video_group); + video_layout->addWidget(new QLabel(tr("Width:")), 0, 0); + video_width_field_ = new QSpinBox(); + video_width_field_->setMaximum(99999); + video_layout->addWidget(video_width_field_, 0, 1); + video_layout->addWidget(new QLabel(tr("Height:")), 1, 0); + video_height_field_ = new QSpinBox(); + video_height_field_->setMaximum(99999); + video_layout->addWidget(video_height_field_, 1, 1); + video_layout->addWidget(new QLabel(tr("Frame Rate:")), 2, 0); + video_frame_rate_field_ = new QComboBox(); + video_layout->addWidget(video_frame_rate_field_, 2, 1); + layout->addWidget(video_group); + + // Set up audio section + QGroupBox* audio_group = new QGroupBox(); + audio_group->setTitle(tr("Audio")); + QGridLayout* audio_layout = new QGridLayout(audio_group); + audio_layout->addWidget(new QLabel(tr("Sample Rate:")), 0, 0); + audio_sample_rate_field_ = new QComboBox(); + // FIXME: No sample rate made + audio_layout->addWidget(audio_sample_rate_field_, 0, 1); + audio_layout->addWidget(new QLabel(tr("Channels:")), 1, 0); + audio_channels_field_ = new QComboBox(); + // FIXME: No channels made + audio_layout->addWidget(audio_channels_field_, 1, 1); + layout->addWidget(audio_group); + + // Set up available frame rates + frame_rate_list_ = Core::SupportedFrameRates(); + foreach (const rational& fr, frame_rate_list_) { + video_frame_rate_field_->addItem(Core::FrameRateToString(fr)); + } + + // Set up available sample rates + sample_rate_list_ = Core::SupportedSampleRates(); + foreach (const int& sr, sample_rate_list_) { + audio_sample_rate_field_->addItem(Core::SampleRateToString(sr)); + } + + // Set up available channel layouts + channel_layout_list_ = Core::SupportedChannelLayouts(); + foreach (const uint64_t& ch_layout, channel_layout_list_) { + audio_channels_field_->addItem(Core::ChannelLayoutToString(ch_layout), QVariant::fromValue(ch_layout)); + } + + // Set values based on input sequence + video_width_field_->setValue(sequence->video_params().width()); + video_height_field_->setValue(sequence->video_params().height()); + + int frame_rate_index = frame_rate_list_.indexOf(sequence->video_params().time_base().flipped()); + video_frame_rate_field_->setCurrentIndex(frame_rate_index); + + int sample_rate_index = sample_rate_list_.indexOf(sequence->audio_params().sample_rate()); + audio_sample_rate_field_->setCurrentIndex(sample_rate_index); + + for (int i=0;icount();i++) { + if (audio_channels_field_->itemData(i).toULongLong() == sequence->audio_params().channel_layout()) { + audio_channels_field_->setCurrentIndex(i); + break; + } + } + + layout->addStretch(); + + QPushButton* save_preset_btn = new QPushButton(tr("Save Preset")); + connect(save_preset_btn, &QPushButton::clicked, this, &SequenceDialogParameterTab::SavePresetClicked); + layout->addWidget(save_preset_btn); +} + +int SequenceDialogParameterTab::GetSelectedVideoWidth() const +{ + return video_width_field_->value(); +} + +int SequenceDialogParameterTab::GetSelectedVideoHeight() const +{ + return video_height_field_->value(); +} + +const rational &SequenceDialogParameterTab::GetSelectedVideoFrameRate() const +{ + return frame_rate_list_.at(video_frame_rate_field_->currentIndex()); +} + +int SequenceDialogParameterTab::GetSelectedAudioSampleRate() const +{ + return sample_rate_list_.at(audio_sample_rate_field_->currentIndex()); +} + +uint64_t SequenceDialogParameterTab::GetSelectedAudioChannelLayout() const +{ + return audio_channels_field_->currentData().toULongLong(); +} + +void SequenceDialogParameterTab::PresetChanged(const SequencePreset &preset) +{ + video_width_field_->setValue(preset.width); + video_height_field_->setValue(preset.height); + video_frame_rate_field_->setCurrentIndex(frame_rate_list_.indexOf(preset.frame_rate)); + audio_sample_rate_field_->setCurrentIndex(sample_rate_list_.indexOf(preset.sample_rate)); + audio_channels_field_->setCurrentIndex(channel_layout_list_.indexOf(preset.channel_layout)); +} + +void SequenceDialogParameterTab::SavePresetClicked() +{ + emit SaveParametersAsPreset({QString(), + video_width_field_->value(), + video_height_field_->value(), + frame_rate_list_.at(video_frame_rate_field_->currentIndex()), + sample_rate_list_.at(audio_sample_rate_field_->currentIndex()), + channel_layout_list_.at(audio_channels_field_->currentIndex())}); +} + +OLIVE_NAMESPACE_EXIT diff --git a/app/dialog/sequence/sequencedialogparametertab.h b/app/dialog/sequence/sequencedialogparametertab.h new file mode 100644 index 000000000..c38cd754b --- /dev/null +++ b/app/dialog/sequence/sequencedialogparametertab.h @@ -0,0 +1,59 @@ +#ifndef SEQUENCEDIALOGPARAMETERTAB_H +#define SEQUENCEDIALOGPARAMETERTAB_H + +#include +#include +#include + +#include "project/item/sequence/sequence.h" +#include "sequencepreset.h" + +OLIVE_NAMESPACE_ENTER + +class SequenceDialogParameterTab : public QWidget +{ + Q_OBJECT +public: + SequenceDialogParameterTab(Sequence* sequence, QWidget* parent = nullptr); + + int GetSelectedVideoWidth() const; + + int GetSelectedVideoHeight() const; + + const rational& GetSelectedVideoFrameRate() const; + + int GetSelectedAudioSampleRate() const; + + uint64_t GetSelectedAudioChannelLayout() const; + +public slots: + void PresetChanged(const SequencePreset& preset); + +signals: + void SaveParametersAsPreset(const SequencePreset& preset); + +private: + QSpinBox* video_width_field_; + + QSpinBox* video_height_field_; + + QComboBox* video_frame_rate_field_; + + QComboBox* audio_sample_rate_field_; + + QComboBox* audio_channels_field_; + + QList frame_rate_list_; + + QList sample_rate_list_; + + QList channel_layout_list_; + +private slots: + void SavePresetClicked(); + +}; + +OLIVE_NAMESPACE_EXIT + +#endif // SEQUENCEDIALOGPARAMETERTAB_H diff --git a/app/dialog/sequence/sequencedialogpresettab.cpp b/app/dialog/sequence/sequencedialogpresettab.cpp new file mode 100644 index 000000000..b67ff8398 --- /dev/null +++ b/app/dialog/sequence/sequencedialogpresettab.cpp @@ -0,0 +1,365 @@ +#include "sequencedialogpresettab.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common/filefunctions.h" +#include "node/input.h" +#include "ui/icons/icons.h" +#include "widget/menu/menu.h" + +OLIVE_NAMESPACE_ENTER + +const int kDataIsPreset = Qt::UserRole; +const int kDataPresetIsCustomRole = Qt::UserRole + 1; +const int kDataPresetDataRole = Qt::UserRole + 2; + +SequenceDialogPresetTab::SequenceDialogPresetTab(QWidget* parent) : + QWidget(parent) +{ + QVBoxLayout* outer_layout = new QVBoxLayout(this); + outer_layout->setMargin(0); + + preset_tree_ = new QTreeWidget(); + preset_tree_->setColumnCount(1); + preset_tree_->setHeaderLabel(tr("Preset")); + preset_tree_->setContextMenuPolicy(Qt::CustomContextMenu); + connect(preset_tree_, &QTreeWidget::customContextMenuRequested, this, &SequenceDialogPresetTab::ShowContextMenu); + outer_layout->addWidget(preset_tree_); + connect(preset_tree_, &QTreeWidget::currentItemChanged, this, &SequenceDialogPresetTab::SelectedItemChanged); + connect(preset_tree_, &QTreeWidget::itemDoubleClicked, this, &SequenceDialogPresetTab::ItemDoubleClicked); + + // Add "my presets" folder + my_presets_folder_ = CreateFolder(tr("My Presets")); + preset_tree_->addTopLevelItem(my_presets_folder_); + + // Add presets + preset_tree_->addTopLevelItem(CreateHDPresetFolder(tr("4K UHD"), 3840, 2160)); + preset_tree_->addTopLevelItem(CreateHDPresetFolder(tr("1080p"), 1920, 1080)); + preset_tree_->addTopLevelItem(CreateHDPresetFolder(tr("720p"), 1280, 720)); + + preset_tree_->addTopLevelItem(CreateSDPresetFolder(tr("NTSC"), 720, 480, rational(30000, 1001))); + preset_tree_->addTopLevelItem(CreateSDPresetFolder(tr("PAL"), 720, 576, rational(25, 1))); + + // Load custom presets + QFile preset_file(GetCustomPresetFilename()); + if (preset_file.open(QFile::ReadOnly)) { + QXmlStreamReader reader(&preset_file); + + while (XMLReadNextStartElement(&reader)) { + if (reader.name() == QStringLiteral("presets")) { + while (XMLReadNextStartElement(&reader)) { + if (reader.name() == QStringLiteral("preset")) { + SequencePreset p; + + while (XMLReadNextStartElement(&reader)) { + if (reader.name() == QStringLiteral("name")) { + p.name = reader.readElementText(); + } else if (reader.name() == QStringLiteral("width")) { + p.width = reader.readElementText().toInt(); + } else if (reader.name() == QStringLiteral("height")) { + p.height = reader.readElementText().toInt(); + } else if (reader.name() == QStringLiteral("framerate")) { + p.frame_rate = rational::fromString(reader.readElementText()); + } else if (reader.name() == QStringLiteral("samplerate")) { + p.sample_rate = reader.readElementText().toInt(); + } else if (reader.name() == QStringLiteral("chlayout")) { + p.channel_layout = reader.readElementText().toULongLong(); + } else { + reader.skipCurrentElement(); + } + } + + AddItem(my_presets_folder_, p, true); + } else { + reader.skipCurrentElement(); + } + } + } else { + reader.skipCurrentElement(); + } + } + + preset_file.close(); + } +} + +SequenceDialogPresetTab::~SequenceDialogPresetTab() +{ + // Save custom presets to disk + QFile preset_file(GetCustomPresetFilename()); + if (preset_file.open(QFile::WriteOnly)) { + QXmlStreamWriter writer(&preset_file); + writer.setAutoFormatting(true); + + writer.writeStartDocument(); + + writer.writeStartElement(QStringLiteral("presets")); + + foreach (const SequencePreset& p, custom_preset_data_) { + writer.writeStartElement(QStringLiteral("preset")); + + writer.writeTextElement(QStringLiteral("name"), p.name); + writer.writeTextElement(QStringLiteral("width"), QString::number(p.width)); + writer.writeTextElement(QStringLiteral("height"), QString::number(p.height)); + writer.writeTextElement(QStringLiteral("framerate"), p.frame_rate.toString()); + writer.writeTextElement(QStringLiteral("samplerate"), QString::number(p.sample_rate)); + writer.writeTextElement(QStringLiteral("chlayout"), QString::number(p.channel_layout)); + + writer.writeEndElement(); // preset + } + + writer.writeEndElement(); // presets + + writer.writeEndDocument(); + + preset_file.close(); + } +} + +void SequenceDialogPresetTab::SaveParametersAsPreset(SequencePreset preset) +{ + QString preset_name; + int existing_preset; + + forever { + preset_name = GetPresetName(preset_name); + + if (preset_name.isEmpty()) { + // Dialog cancelled - leave function entirely + return; + } + + existing_preset = -1; + for (int i=0; i= 0) { + custom_preset_data_.replace(existing_preset, preset); + } else { + AddItem(my_presets_folder_, preset, true); + } +} + +QTreeWidgetItem* SequenceDialogPresetTab::CreateFolder(const QString &name) +{ + QTreeWidgetItem* folder = new QTreeWidgetItem(); + folder->setText(0, name); + folder->setIcon(0, icon::Folder); + return folder; +} + +QTreeWidgetItem *SequenceDialogPresetTab::CreateHDPresetFolder(const QString &name, int width, int height) +{ + QTreeWidgetItem* parent = CreateFolder(name); + AddItem(parent, {tr("%1 23.976 FPS").arg(name), + width, + height, + rational(24000, 1001), + 48000, + AV_CH_LAYOUT_STEREO}); + AddItem(parent, {tr("%1 25 FPS").arg(name), + width, + height, + rational(25, 1), + 48000, + AV_CH_LAYOUT_STEREO}); + AddItem(parent, {tr("%1 29.97 FPS").arg(name), + width, + height, + rational(30000, 1001), + 48000, + AV_CH_LAYOUT_STEREO}); + AddItem(parent, {tr("%1 50 FPS").arg(name), + width, + height, + rational(50, 1), + 48000, + AV_CH_LAYOUT_STEREO}); + AddItem(parent, {tr("%1 59.94 FPS").arg(name), + width, + height, + rational(60000, 1001), + 48000, + AV_CH_LAYOUT_STEREO}); + return parent; +} + +QTreeWidgetItem *SequenceDialogPresetTab::CreateSDPresetFolder(const QString &name, int width, int height, const rational& frame_rate) +{ + QTreeWidgetItem* parent = CreateFolder(name); + preset_tree_->addTopLevelItem(parent); + AddItem(parent, {tr("%1 Standard").arg(name), + width, + height, + frame_rate, + 48000, + AV_CH_LAYOUT_STEREO}); + AddItem(parent, {tr("%1 Widescreen").arg(name), + width, + height, + frame_rate, + 48000, + AV_CH_LAYOUT_STEREO}); + return parent; +} + +QString SequenceDialogPresetTab::GetPresetName(QString start) +{ + bool ok; + + forever { + start = QInputDialog::getText(this, + tr("Save Preset"), + tr("Set preset name:"), + QLineEdit::Normal, + start, + &ok); + + if (!ok) { + // Dialog cancelled - leave function entirely + return QString(); + } + + if (start.isEmpty()) { + // No preset name entered, start loop over + QMessageBox::critical(this, tr("Invalid preset name"), + tr("You must enter a preset name"), QMessageBox::Ok); + } else { + break; + } + } + + return start; +} + +QTreeWidgetItem *SequenceDialogPresetTab::GetSelectedItem() +{ + QList selected_items = preset_tree_->selectedItems(); + + if (selected_items.isEmpty()) { + return nullptr; + } else { + return selected_items.first(); + } +} + +QTreeWidgetItem *SequenceDialogPresetTab::GetSelectedCustomPreset() +{ + QTreeWidgetItem* sel = GetSelectedItem(); + + if (sel + && sel->data(0, kDataIsPreset).toBool() + && sel->data(0, kDataPresetIsCustomRole).toBool()) { + return sel; + } + + return nullptr; +} + +QString SequenceDialogPresetTab::GetCustomPresetFilename() +{ + return QDir(FileFunctions::GetConfigurationLocation()).filePath(QStringLiteral("presets")); +} + +void SequenceDialogPresetTab::AddItem(QTreeWidgetItem *folder, const SequencePreset& preset, bool is_custom, const QString &description) +{ + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(0, preset.name); + item->setIcon(0, icon::Video); + item->setToolTip(0, description); + item->setData(0, kDataIsPreset, true); + item->setData(0, kDataPresetIsCustomRole, is_custom); + + QList& list = is_custom ? custom_preset_data_ : default_preset_data_; + item->setData(0, kDataPresetDataRole, list.size()); + list.append(preset); + + folder->addChild(item); +} + +void SequenceDialogPresetTab::SelectedItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous) +{ + Q_UNUSED(previous) + + if (current->data(0, kDataIsPreset).toBool()) { + int preset_index = current->data(0, kDataPresetDataRole).toInt(); + + const SequencePreset& preset_data = (current->data(0, kDataPresetIsCustomRole).toBool()) + ? custom_preset_data_.at(preset_index) + : default_preset_data_.at(preset_index); + + emit PresetChanged(preset_data); + } +} + +void SequenceDialogPresetTab::ItemDoubleClicked(QTreeWidgetItem *item, int column) +{ + Q_UNUSED(column) + + if (item->data(0, kDataIsPreset).toBool()) { + emit PresetAccepted(); + } +} + +void SequenceDialogPresetTab::ShowContextMenu() +{ + QTreeWidgetItem* sel = GetSelectedCustomPreset(); + + if (sel) { + Menu m(this); + + QAction* delete_action = m.addAction(tr("Delete Preset")); + connect(delete_action, &QAction::triggered, this, &SequenceDialogPresetTab::DeleteSelectedPreset); + + m.exec(QCursor::pos()); + } +} + +void SequenceDialogPresetTab::DeleteSelectedPreset() +{ + QTreeWidgetItem* sel = GetSelectedCustomPreset(); + + if (sel) { + int preset_index = sel->data(0, kDataPresetDataRole).toInt(); + + // Shift all items whose index was after this preset forward + for (int i=0; ichildCount(); i++) { + QTreeWidgetItem* custom_item = my_presets_folder_->child(i); + int this_item_index = custom_item->data(0, kDataPresetDataRole).toInt(); + + if (this_item_index > preset_index) { + custom_item->setData(0, kDataPresetDataRole, this_item_index - 1); + } + } + + // Remove the preset + custom_preset_data_.removeAt(preset_index); + + // Delete the item + delete sel; + } +} + +OLIVE_NAMESPACE_EXIT diff --git a/app/dialog/sequence/sequencedialogpresettab.h b/app/dialog/sequence/sequencedialogpresettab.h new file mode 100644 index 000000000..c35bd20eb --- /dev/null +++ b/app/dialog/sequence/sequencedialogpresettab.h @@ -0,0 +1,67 @@ +#ifndef SEQUENCEDIALOGPRESETTAB_H +#define SEQUENCEDIALOGPRESETTAB_H + +#include +#include +#include + +#include "sequencepreset.h" + +OLIVE_NAMESPACE_ENTER + +class SequenceDialogPresetTab : public QWidget +{ + Q_OBJECT +public: + SequenceDialogPresetTab(QWidget* parent = nullptr); + + virtual ~SequenceDialogPresetTab() override; + +public slots: + void SaveParametersAsPreset(SequencePreset preset); + +signals: + void PresetChanged(const SequencePreset& preset); + + void PresetAccepted(); + +private: + QTreeWidgetItem *CreateFolder(const QString& name); + + QTreeWidgetItem *CreateHDPresetFolder(const QString& name, int width, int height); + + QTreeWidgetItem *CreateSDPresetFolder(const QString& name, int width, int height, const rational &frame_rate); + + QString GetPresetName(QString start); + + QTreeWidgetItem* GetSelectedItem(); + QTreeWidgetItem* GetSelectedCustomPreset(); + + static QString GetCustomPresetFilename(); + + void AddItem(QTreeWidgetItem* folder, + const SequencePreset& preset, + bool is_custom = false, + const QString& description = QString()); + + QTreeWidget* preset_tree_; + + QTreeWidgetItem* my_presets_folder_; + + QList default_preset_data_; + QList custom_preset_data_; + +private slots: + void SelectedItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); + + void ItemDoubleClicked(QTreeWidgetItem *item, int column); + + void ShowContextMenu(); + + void DeleteSelectedPreset(); + +}; + +OLIVE_NAMESPACE_EXIT + +#endif // SEQUENCEDIALOGPRESETTAB_H diff --git a/app/dialog/sequence/sequencepreset.h b/app/dialog/sequence/sequencepreset.h new file mode 100644 index 000000000..b7101be19 --- /dev/null +++ b/app/dialog/sequence/sequencepreset.h @@ -0,0 +1,19 @@ +#ifndef SEQUENCEPARAM_H +#define SEQUENCEPARAM_H + +#include "common/rational.h" + +OLIVE_NAMESPACE_ENTER + +struct SequencePreset { + QString name; + int width; + int height; + rational frame_rate; + int sample_rate; + uint64_t channel_layout; +}; + +OLIVE_NAMESPACE_EXIT + +#endif // SEQUENCEPARAM_H