diff --git a/src/citra_qt/dumping/dumping_dialog.cpp b/src/citra_qt/dumping/dumping_dialog.cpp index e728747bc..70d165c01 100644 --- a/src/citra_qt/dumping/dumping_dialog.cpp +++ b/src/citra_qt/dumping/dumping_dialog.cpp @@ -15,6 +15,9 @@ DumpingDialog::DumpingDialog(QWidget* parent) ui->setupUi(this); + format_generic_options = VideoDumper::GetFormatGenericOptions(); + encoder_generic_options = VideoDumper::GetEncoderGenericOptions(); + connect(ui->pathExplore, &QToolButton::clicked, this, &DumpingDialog::OnToolButtonClicked); connect(ui->buttonBox, &QDialogButtonBox::accepted, [this] { if (ui->pathLineEdit->text().isEmpty()) { @@ -27,17 +30,17 @@ DumpingDialog::DumpingDialog(QWidget* parent) connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &DumpingDialog::reject); connect(ui->formatOptionsButton, &QToolButton::clicked, [this] { OpenOptionsDialog(formats.at(ui->formatComboBox->currentData().toUInt()).options, - ui->formatOptionsLineEdit); + format_generic_options, ui->formatOptionsLineEdit); }); connect(ui->videoEncoderOptionsButton, &QToolButton::clicked, [this] { OpenOptionsDialog( video_encoders.at(ui->videoEncoderComboBox->currentData().toUInt()).options, - ui->videoEncoderOptionsLineEdit); + encoder_generic_options, ui->videoEncoderOptionsLineEdit); }); connect(ui->audioEncoderOptionsButton, &QToolButton::clicked, [this] { OpenOptionsDialog( audio_encoders.at(ui->audioEncoderComboBox->currentData().toUInt()).options, - ui->audioEncoderOptionsLineEdit); + encoder_generic_options, ui->audioEncoderOptionsLineEdit); }); SetConfiguration(); @@ -177,9 +180,10 @@ void DumpingDialog::OnToolButtonClicked() { } } -void DumpingDialog::OpenOptionsDialog(const std::vector& options, +void DumpingDialog::OpenOptionsDialog(const std::vector& specific_options, + const std::vector& generic_options, QLineEdit* line_edit) { - OptionsDialog dialog(this, options, line_edit->text().toStdString()); + OptionsDialog dialog(this, specific_options, generic_options, line_edit->text().toStdString()); if (dialog.exec() != QDialog::DialogCode::Accepted) { return; } diff --git a/src/citra_qt/dumping/dumping_dialog.h b/src/citra_qt/dumping/dumping_dialog.h index c2b0999ea..284f215c3 100644 --- a/src/citra_qt/dumping/dumping_dialog.h +++ b/src/citra_qt/dumping/dumping_dialog.h @@ -27,7 +27,8 @@ private: void PopulateEncoders(); void SetConfiguration(); void OnToolButtonClicked(); - void OpenOptionsDialog(const std::vector& options, + void OpenOptionsDialog(const std::vector& specific_options, + const std::vector& generic_options, QLineEdit* line_edit); std::unique_ptr ui; @@ -35,6 +36,8 @@ private: QString last_path; std::vector formats; + std::vector format_generic_options; std::vector video_encoders; std::vector audio_encoders; + std::vector encoder_generic_options; }; diff --git a/src/citra_qt/dumping/options_dialog.cpp b/src/citra_qt/dumping/options_dialog.cpp index 419272dd1..e75fc61c0 100644 --- a/src/citra_qt/dumping/options_dialog.cpp +++ b/src/citra_qt/dumping/options_dialog.cpp @@ -9,7 +9,10 @@ constexpr char UNSET_TEXT[] = QT_TR_NOOP("[not set]"); -void OptionsDialog::PopulateOptions(const std::string& current_value) { +void OptionsDialog::PopulateOptions() { + const auto& options = ui->specificRadioButton->isChecked() ? specific_options : generic_options; + ui->main->clear(); + ui->main->setSortingEnabled(false); for (std::size_t i = 0; i < options.size(); ++i) { const auto& option = options.at(i); auto* item = new QTreeWidgetItem( @@ -18,9 +21,13 @@ void OptionsDialog::PopulateOptions(const std::string& current_value) { item->setData(1, Qt::UserRole, static_cast(i)); // ID ui->main->addTopLevelItem(item); } + ui->main->setSortingEnabled(true); + ui->main->sortItems(0, Qt::AscendingOrder); } -void OptionsDialog::OnSetOptionValue(int id) { +void OptionsDialog::OnSetOptionValue(QTreeWidgetItem* item) { + const auto& options = ui->specificRadioButton->isChecked() ? specific_options : generic_options; + const int id = item->data(1, Qt::UserRole).toInt(); OptionSetDialog dialog(this, options[id], current_values.Get(options[id].name, options[id].default_value)); if (dialog.exec() != QDialog::DialogCode::Accepted) { @@ -33,27 +40,29 @@ void OptionsDialog::OnSetOptionValue(int id) { } else { current_values.Erase(options[id].name); } - ui->main->invisibleRootItem()->child(id)->setText(1, is_set ? QString::fromStdString(value) - : tr(UNSET_TEXT)); + item->setText(1, is_set ? QString::fromStdString(value) : tr(UNSET_TEXT)); } std::string OptionsDialog::GetCurrentValue() const { return current_values.Serialize(); } -OptionsDialog::OptionsDialog(QWidget* parent, std::vector options_, +OptionsDialog::OptionsDialog(QWidget* parent, + std::vector specific_options_, + std::vector generic_options_, const std::string& current_value) - : QDialog(parent), ui(std::make_unique()), options(std::move(options_)), + : QDialog(parent), ui(std::make_unique()), + specific_options(std::move(specific_options_)), generic_options(std::move(generic_options_)), current_values(current_value) { ui->setupUi(this); - PopulateOptions(current_value); + PopulateOptions(); - connect(ui->main, &QTreeWidget::itemDoubleClicked, [this](QTreeWidgetItem* item, int column) { - OnSetOptionValue(item->data(1, Qt::UserRole).toInt()); - }); + connect(ui->main, &QTreeWidget::itemDoubleClicked, + [this](QTreeWidgetItem* item, int column) { OnSetOptionValue(item); }); connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &OptionsDialog::accept); connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &OptionsDialog::reject); + connect(ui->specificRadioButton, &QRadioButton::toggled, this, &OptionsDialog::PopulateOptions); } OptionsDialog::~OptionsDialog() = default; diff --git a/src/citra_qt/dumping/options_dialog.h b/src/citra_qt/dumping/options_dialog.h index 9c6f92112..d9a29e2dc 100644 --- a/src/citra_qt/dumping/options_dialog.h +++ b/src/citra_qt/dumping/options_dialog.h @@ -8,6 +8,8 @@ #include "common/param_package.h" #include "core/dumping/ffmpeg_backend.h" +class QTreeWidgetItem; + namespace Ui { class OptionsDialog; } @@ -16,17 +18,19 @@ class OptionsDialog : public QDialog { Q_OBJECT public: - explicit OptionsDialog(QWidget* parent, std::vector options, + explicit OptionsDialog(QWidget* parent, std::vector specific_options, + std::vector generic_options, const std::string& current_value); ~OptionsDialog() override; std::string GetCurrentValue() const; private: - void PopulateOptions(const std::string& current_value); - void OnSetOptionValue(int id); + void PopulateOptions(); + void OnSetOptionValue(QTreeWidgetItem* item); std::unique_ptr ui; - std::vector options; + std::vector specific_options; + std::vector generic_options; Common::ParamPackage current_values; }; diff --git a/src/citra_qt/dumping/options_dialog.ui b/src/citra_qt/dumping/options_dialog.ui index 21c7c6676..e8bd7fb41 100644 --- a/src/citra_qt/dumping/options_dialog.ui +++ b/src/citra_qt/dumping/options_dialog.ui @@ -6,8 +6,8 @@ 0 0 - 600 - 300 + 650 + 350 @@ -24,6 +24,27 @@ + + + + + + Specific + + + true + + + + + + + Generic + + + + + diff --git a/src/core/dumping/ffmpeg_backend.cpp b/src/core/dumping/ffmpeg_backend.cpp index 17a2c4cd7..6829b2d45 100644 --- a/src/core/dumping/ffmpeg_backend.cpp +++ b/src/core/dumping/ffmpeg_backend.cpp @@ -754,8 +754,6 @@ std::vector GetOptionList(const AVClass* av_class, bool search_child std::vector ListEncoders(AVMediaType type) { InitializeFFmpegLibraries(); - const auto general_options = GetOptionList(avcodec_get_class(), false); - std::vector out; const AVCodec* current = nullptr; @@ -768,19 +766,19 @@ std::vector ListEncoders(AVMediaType type) { if (!av_codec_is_encoder(current) || current->type != type) { continue; } - auto options = GetOptionList(current->priv_class, true); - options.insert(options.end(), general_options.begin(), general_options.end()); - out.push_back( - {current->name, ToStdString(current->long_name), current->id, std::move(options)}); + out.push_back({current->name, ToStdString(current->long_name), current->id, + GetOptionList(current->priv_class, true)}); } return out; } +std::vector GetEncoderGenericOptions() { + return GetOptionList(avcodec_get_class(), false); +} + std::vector ListFormats() { InitializeFFmpegLibraries(); - const auto general_options = GetOptionList(avformat_get_class(), false); - std::vector out; const AVOutputFormat* current = nullptr; @@ -790,9 +788,6 @@ std::vector ListFormats() { void* data = nullptr; // For libavformat to save the iteration state while ((current = av_muxer_iterate(&data))) { #endif - auto options = GetOptionList(current->priv_class, true); - options.insert(options.end(), general_options.begin(), general_options.end()); - std::vector extensions; Common::SplitString(ToStdString(current->extensions), ',', extensions); @@ -816,9 +811,13 @@ std::vector ListFormats() { out.push_back({current->name, ToStdString(current->long_name), std::move(extensions), std::move(supported_video_codecs), std::move(supported_audio_codecs), - std::move(options)}); + GetOptionList(current->priv_class, true)}); } return out; } +std::vector GetFormatGenericOptions() { + return GetOptionList(avformat_get_class(), false); +} + } // namespace VideoDumper diff --git a/src/core/dumping/ffmpeg_backend.h b/src/core/dumping/ffmpeg_backend.h index e2c605c8c..d9f8d8807 100644 --- a/src/core/dumping/ffmpeg_backend.h +++ b/src/core/dumping/ffmpeg_backend.h @@ -227,6 +227,8 @@ struct FormatInfo { }; std::vector ListEncoders(AVMediaType type); +std::vector GetEncoderGenericOptions(); std::vector ListFormats(); +std::vector GetFormatGenericOptions(); } // namespace VideoDumper