#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, 6)); preset_tree_->addTopLevelItem(CreateHDPresetFolder(tr("1080p"), 1920, 1080, 3)); preset_tree_->addTopLevelItem(CreateHDPresetFolder(tr("720p"), 1280, 720, 2)); preset_tree_->addTopLevelItem(CreateSDPresetFolder(tr("NTSC"), 720, 480, rational(30000, 1001), 1)); preset_tree_->addTopLevelItem(CreateSDPresetFolder(tr("PAL"), 720, 576, rational(25, 1), 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 if (reader.name() == QStringLiteral("divider")) { p.preview_divider = reader.readElementText().toInt(); } else if (reader.name() == QStringLiteral("format")) { p.preview_format = static_cast(reader.readElementText().toInt()); } 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.writeTextElement(QStringLiteral("divider"), QString::number(p.preview_divider)); writer.writeTextElement(QStringLiteral("format"), QString::number(p.preview_format)); 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, int divider) { QTreeWidgetItem* parent = CreateFolder(name); AddItem(parent, {tr("%1 23.976 FPS").arg(name), width, height, rational(24000, 1001), 48000, AV_CH_LAYOUT_STEREO, divider, PixelFormat::PIX_FMT_RGBA16F}); AddItem(parent, {tr("%1 25 FPS").arg(name), width, height, rational(25, 1), 48000, AV_CH_LAYOUT_STEREO, divider, PixelFormat::PIX_FMT_RGBA16F}); AddItem(parent, {tr("%1 29.97 FPS").arg(name), width, height, rational(30000, 1001), 48000, AV_CH_LAYOUT_STEREO, divider, PixelFormat::PIX_FMT_RGBA16F}); AddItem(parent, {tr("%1 50 FPS").arg(name), width, height, rational(50, 1), 48000, AV_CH_LAYOUT_STEREO, divider, PixelFormat::PIX_FMT_RGBA16F}); AddItem(parent, {tr("%1 59.94 FPS").arg(name), width, height, rational(60000, 1001), 48000, AV_CH_LAYOUT_STEREO, divider, PixelFormat::PIX_FMT_RGBA16F}); return parent; } QTreeWidgetItem *SequenceDialogPresetTab::CreateSDPresetFolder(const QString &name, int width, int height, const rational& frame_rate, int divider) { QTreeWidgetItem* parent = CreateFolder(name); preset_tree_->addTopLevelItem(parent); AddItem(parent, {tr("%1 Standard").arg(name), width, height, frame_rate, 48000, AV_CH_LAYOUT_STEREO, divider, PixelFormat::PIX_FMT_RGBA16F}); AddItem(parent, {tr("%1 Widescreen").arg(name), width, height, frame_rate, 48000, AV_CH_LAYOUT_STEREO, divider, PixelFormat::PIX_FMT_RGBA16F}); 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