From 56c9a37e5a45705e8bfb47cf95a7416bb6082918 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Wed, 29 Aug 2018 11:34:36 -0400 Subject: [PATCH] Qt: initial core options dialog --- Makefile.common | 2 + griffin/griffin_cpp.cpp | 1 + intl/msg_hash_ja.h | 2 + intl/msg_hash_us.h | 6 +- menu/cbs/menu_cbs_ok.c | 4 +- msg_hash.h | 1 + ui/drivers/qt/coreoptionsdialog.cpp | 308 ++++++++++++++++++++++++++++ ui/drivers/qt/coreoptionsdialog.h | 39 ++++ ui/drivers/qt/ui_qt_window.cpp | 19 ++ ui/drivers/ui_qt.cpp | 1 + ui/drivers/ui_qt.h | 5 + 11 files changed, 385 insertions(+), 3 deletions(-) create mode 100644 ui/drivers/qt/coreoptionsdialog.cpp create mode 100644 ui/drivers/qt/coreoptionsdialog.h diff --git a/Makefile.common b/Makefile.common index d32bea96df..125afe8532 100644 --- a/Makefile.common +++ b/Makefile.common @@ -346,6 +346,7 @@ OBJ += ui/drivers/ui_qt.o \ ui/drivers/qt/ui_qt_msg_window.o \ ui/drivers/qt/flowlayout.o \ ui/drivers/qt/shaderparamsdialog.o \ + ui/drivers/qt/coreoptionsdialog.o \ ui/drivers/qt/filedropwidget.o \ ui/drivers/qt/coreinfodialog.o \ ui/drivers/qt/playlistentrydialog.o \ @@ -360,6 +361,7 @@ MOC_HEADERS += ui/drivers/ui_qt.h \ ui/drivers/qt/ui_qt_load_core_window.h \ ui/drivers/qt/flowlayout.h \ ui/drivers/qt/shaderparamsdialog.h \ + ui/drivers/qt/coreoptionsdialog.h \ ui/drivers/qt/filedropwidget.h \ ui/drivers/qt/coreinfodialog.h \ ui/drivers/qt/playlistentrydialog.h \ diff --git a/griffin/griffin_cpp.cpp b/griffin/griffin_cpp.cpp index 56f15070f7..c3b2bc7116 100644 --- a/griffin/griffin_cpp.cpp +++ b/griffin/griffin_cpp.cpp @@ -43,6 +43,7 @@ UI #include "../ui/drivers/qt/ui_qt_application.cpp" #include "../ui/drivers/qt/flowlayout.cpp" #include "../ui/drivers/qt/shaderparamsdialog.cpp" +#include "../ui/drivers/qt/coreoptionsdialog.cpp" #include "../ui/drivers/qt/filedropwidget.cpp" #include "../ui/drivers/qt/coreinfodialog.cpp" #include "../ui/drivers/qt/playlistentrydialog.cpp" diff --git a/intl/msg_hash_ja.h b/intl/msg_hash_ja.h index ed2daaa004..b58764d5ea 100644 --- a/intl/msg_hash_ja.h +++ b/intl/msg_hash_ja.h @@ -3804,3 +3804,5 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_PACK_DOWNLOADED_SUCCESSFULLY, "サムネイルのダウンロードが成功しました。") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_PLAYLIST_THUMBNAIL_PROGRESS, "成功した数: %1 失敗した数: %2") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_CORE_OPTIONS, + "コア設定") diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 0f39b633c3..67eb6e7518 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -7425,4 +7425,8 @@ MSG_HASH( MSG_HASH( MSG_FAILED_TO_SET_DISK, "Failed to set disk" - ) \ No newline at end of file + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_QT_CORE_OPTIONS, + "Core Options" + ) diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index 6135befeed..69991840ff 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -847,7 +847,7 @@ int generic_action_ok_displaylist_push(const char *path, setting->max = (int) pow(2,pow((double) 2,cheat_manager_state.working_cheat.memory_search_size))-1; setting = menu_setting_find(msg_hash_to_str(MENU_ENUM_LABEL_CHEAT_ADDRESS_BIT_POSITION)); if ( setting ) - { + { int max_bit_position = cheat_manager_state.working_cheat.memory_search_size<3 ? 7 : 0 ; setting->max = max_bit_position ; } @@ -3498,7 +3498,7 @@ static int action_ok_option_create(const char *path, return false; } - if(config_file_write(conf, game_path)) + if (config_file_write(conf, game_path)) { runloop_msg_queue_push( msg_hash_to_str(MSG_CORE_OPTIONS_FILE_CREATED_SUCCESSFULLY), diff --git a/msg_hash.h b/msg_hash.h index 10661c8675..c68223c761 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -2012,6 +2012,7 @@ enum msg_hash_enums MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_ALL_THUMBNAILS_THIS_PLAYLIST, MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_PACK_DOWNLOADED_SUCCESSFULLY, MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_PLAYLIST_THUMBNAIL_PROGRESS, + MENU_ENUM_LABEL_VALUE_QT_CORE_OPTIONS, MENU_LABEL(MIDI_INPUT), MENU_LABEL(MIDI_OUTPUT), diff --git a/ui/drivers/qt/coreoptionsdialog.cpp b/ui/drivers/qt/coreoptionsdialog.cpp new file mode 100644 index 0000000000..088b3e7aef --- /dev/null +++ b/ui/drivers/qt/coreoptionsdialog.cpp @@ -0,0 +1,308 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "coreoptionsdialog.h" +#include "../ui_qt.h" + +extern "C" { +#include +#include +#include +#include "../../../command.h" +#include "../../../configuration.h" +#include "../../../retroarch.h" +#include "../../../paths.h" +#include "../../../file_path_special.h" +#include "../../../managers/core_option_manager.h" +} + +CoreOptionsDialog::CoreOptionsDialog(QWidget *parent) : + QDialog(parent) + ,m_layout() + ,m_scrollArea() +{ + setWindowTitle(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CORE_OPTIONS)); + setObjectName("coreOptionsDialog"); + + resize(720, 480); + + QTimer::singleShot(0, this, SLOT(clearLayout())); +} + +CoreOptionsDialog::~CoreOptionsDialog() +{ +} + +void CoreOptionsDialog::resizeEvent(QResizeEvent *event) +{ + QDialog::resizeEvent(event); + + if (!m_scrollArea) + return; + + m_scrollArea->resize(event->size()); + + emit resized(event->size()); +} + +void CoreOptionsDialog::closeEvent(QCloseEvent *event) +{ + QDialog::closeEvent(event); + + emit closed(); +} + +void CoreOptionsDialog::paintEvent(QPaintEvent *event) +{ + QStyleOption o; + QPainter p; + o.initFrom(this); + p.begin(this); + style()->drawPrimitive( + QStyle::PE_Widget, &o, &p, this); + p.end(); + + QDialog::paintEvent(event); +} + +void CoreOptionsDialog::clearLayout() +{ + QWidget *widget = NULL; + + if (m_scrollArea) + { + foreach (QObject *obj, children()) + { + obj->deleteLater(); + } + } + + m_layout = new QVBoxLayout(); + + widget = new QWidget(); + widget->setLayout(m_layout); + widget->setObjectName("coreOptionsWidget"); + + m_scrollArea = new QScrollArea(); + + m_scrollArea->setParent(this); + m_scrollArea->setWidgetResizable(true); + m_scrollArea->setWidget(widget); + m_scrollArea->setObjectName("coreOptionsScrollArea"); + m_scrollArea->show(); +} + +void CoreOptionsDialog::reload() +{ + buildLayout(); +} + +void CoreOptionsDialog::onSaveGameSpecificOptions() +{ + char game_path[PATH_MAX_LENGTH]; + config_file_t *conf = NULL; + + game_path[0] = '\0'; + + if (!retroarch_validate_game_options(game_path, sizeof(game_path), true)) + { + QMessageBox::critical(this, msg_hash_to_str(MSG_ERROR), msg_hash_to_str(MSG_ERROR_SAVING_CORE_OPTIONS_FILE)); + return; + } + + conf = config_file_new(game_path); + + if (!conf) + { + conf = config_file_new(NULL); + + if (!conf) + { + QMessageBox::critical(this, msg_hash_to_str(MSG_ERROR), msg_hash_to_str(MSG_ERROR_SAVING_CORE_OPTIONS_FILE)); + return; + } + } + + if (config_file_write(conf, game_path)) + { + runloop_msg_queue_push( + msg_hash_to_str(MSG_CORE_OPTIONS_FILE_CREATED_SUCCESSFULLY), + 1, 100, true); + path_set(RARCH_PATH_CORE_OPTIONS, game_path); + } + + config_file_free(conf); +} + +void CoreOptionsDialog::onCoreOptionComboBoxCurrentIndexChanged(int index) +{ + QComboBox *comboBox = qobject_cast(sender()); + QString key, val; + size_t opts = 0; + unsigned i, k; + + if (!comboBox) + return; + + key = comboBox->itemData(index, Qt::UserRole).toString(); + val = comboBox->itemText(index); + + if (rarch_ctl(RARCH_CTL_HAS_CORE_OPTIONS, NULL)) + { + rarch_ctl(RARCH_CTL_GET_CORE_OPTION_SIZE, &opts); + + if (opts) + { + core_option_manager_t *coreopts = NULL; + + rarch_ctl(RARCH_CTL_CORE_OPTIONS_LIST_GET, &coreopts); + + if (coreopts) + { + for (i = 0; i < opts; i++) + { + QString optKey; + struct core_option *option = static_cast(&coreopts->opts[i]); + + if (!option) + continue; + + optKey = option->key; + + if (key == optKey) + { + for (k = 0; k < option->vals->size; k++) + { + QString str = option->vals->elems[k].data; + + if (!str.isEmpty() && str == val) + core_option_manager_set_val(coreopts, i, k); + } + } + } + } + } + } +} + +void CoreOptionsDialog::buildLayout() +{ + QFormLayout *form = NULL; + settings_t *settings = config_get_ptr(); + size_t opts = 0; + int i; + unsigned j, k; + + clearLayout(); + + if (rarch_ctl(RARCH_CTL_HAS_CORE_OPTIONS, NULL)) + { + rarch_ctl(RARCH_CTL_GET_CORE_OPTION_SIZE, &opts); + + if (opts) + { + core_option_manager_t *coreopts = NULL; + + form = new QFormLayout(); + + if (settings->bools.game_specific_options) + { + rarch_system_info_t *system = runloop_get_system_info(); + QString contentLabel; + QString label; + + if (system) + contentLabel = QFileInfo(path_get(RARCH_PATH_BASENAME)).completeBaseName(); + + if (!contentLabel.isEmpty()) + { + if (!rarch_ctl(RARCH_CTL_IS_GAME_OPTIONS_ACTIVE, NULL)) + label = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GAME_SPECIFIC_OPTIONS_CREATE); + else + label = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GAME_SPECIFIC_OPTIONS_IN_USE); + + if (!label.isEmpty()) + { + QHBoxLayout *gameOptionsLayout = new QHBoxLayout(); + QPushButton *button = new QPushButton(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_SAVE), this); + + connect(button, SIGNAL(clicked()), this, SLOT(onSaveGameSpecificOptions())); + + gameOptionsLayout->addWidget(new QLabel(contentLabel, this)); + gameOptionsLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Preferred)); + gameOptionsLayout->addWidget(button); + + form->addRow(label, gameOptionsLayout); + } + } + } + + rarch_ctl(RARCH_CTL_CORE_OPTIONS_LIST_GET, &coreopts); + + if (coreopts) + { + for (j = 0; j < opts; j++) + { + QString desc = core_option_manager_get_desc(coreopts, j); + QString val = core_option_manager_get_val(coreopts, j); + QComboBox *comboBox = NULL; + struct core_option *option = NULL; + + if (desc.isEmpty() || !coreopts->opts) + continue; + + option = static_cast(&coreopts->opts[j]); + + if (!option->vals || option->vals->size == 0) + continue; + + comboBox = new QComboBox(this); + + for (k = 0; k < option->vals->size; k++) + { + comboBox->addItem(option->vals->elems[k].data, option->key); + } + + comboBox->setCurrentText(val); + + /* Only connect the signal after setting the default item */ + connect(comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onCoreOptionComboBoxCurrentIndexChanged(int))); + + form->addRow(desc, comboBox); + } + + m_layout->addLayout(form); + } + } + } + + if (!opts) + { + QLabel *noParamsLabel = new QLabel(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_CORE_OPTIONS_AVAILABLE), this); + noParamsLabel->setAlignment(Qt::AlignCenter); + + m_layout->addWidget(noParamsLabel); + } + + m_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding)); + + resize(width() + 1, height()); + show(); + resize(width() - 1, height()); +} diff --git a/ui/drivers/qt/coreoptionsdialog.h b/ui/drivers/qt/coreoptionsdialog.h new file mode 100644 index 0000000000..2a9c29023e --- /dev/null +++ b/ui/drivers/qt/coreoptionsdialog.h @@ -0,0 +1,39 @@ +#ifndef COREOPTIONSDIALOG_H +#define COREOPTIONSDIALOG_H + +#include +#include + +class QCloseEvent; +class QResizeEvent; +class QVBoxLayout; +class QFormLayout; +class QLayout; +class QScrollArea; + +class CoreOptionsDialog : public QDialog +{ + Q_OBJECT +public: + CoreOptionsDialog(QWidget *parent = 0); + ~CoreOptionsDialog(); +signals: + void closed(); + void resized(QSize size); +public slots: + void reload(); +private slots: + void clearLayout(); + void buildLayout(); + void onSaveGameSpecificOptions(); + void onCoreOptionComboBoxCurrentIndexChanged(int index); +private: + QPointer m_layout; + QPointer m_scrollArea; +protected: + void closeEvent(QCloseEvent *event); + void resizeEvent(QResizeEvent *event); + void paintEvent(QPaintEvent *event); +}; + +#endif diff --git a/ui/drivers/qt/ui_qt_window.cpp b/ui/drivers/qt/ui_qt_window.cpp index 1699c9a36c..f882057ddb 100644 --- a/ui/drivers/qt/ui_qt_window.cpp +++ b/ui/drivers/qt/ui_qt_window.cpp @@ -45,6 +45,7 @@ #include "ui_qt_themes.h" #include "flowlayout.h" #include "shaderparamsdialog.h" +#include "coreoptionsdialog.h" #include "filedropwidget.h" #include "coreinfodialog.h" #include "playlistentrydialog.h" @@ -316,6 +317,7 @@ MainWindow::MainWindow(QWidget *parent) : ,m_playlistEntryDialog(NULL) ,m_statusMessageElapsedTimer() ,m_shaderParamsDialog(new ShaderParamsDialog()) + ,m_coreOptionsDialog(new CoreOptionsDialog()) ,m_networkManager(new QNetworkAccessManager(this)) ,m_updateProgressDialog(new QProgressDialog()) ,m_updateFile() @@ -574,6 +576,7 @@ MainWindow::MainWindow(QWidget *parent) : connect(this, SIGNAL(gotStatusMessage(QString,unsigned,unsigned,bool)), this, SLOT(onGotStatusMessage(QString,unsigned,unsigned,bool)), Qt::AutoConnection); connect(this, SIGNAL(gotReloadPlaylists()), this, SLOT(onGotReloadPlaylists()), Qt::AutoConnection); connect(this, SIGNAL(gotReloadShaderParams()), this, SLOT(onGotReloadShaderParams()), Qt::AutoConnection); + connect(this, SIGNAL(gotReloadCoreOptions()), this, SLOT(onGotReloadCoreOptions()), Qt::AutoConnection); /* these are always queued */ connect(this, SIGNAL(showErrorMessageDeferred(QString)), this, SLOT(onShowErrorMessage(QString)), Qt::QueuedConnection); @@ -1055,12 +1058,28 @@ void MainWindow::onShaderParamsClicked() onGotReloadShaderParams(); } +void MainWindow::onCoreOptionsClicked() +{ + if (!m_coreOptionsDialog) + return; + + m_coreOptionsDialog->show(); + + onGotReloadCoreOptions(); +} + void MainWindow::onGotReloadShaderParams() { if (m_shaderParamsDialog && m_shaderParamsDialog->isVisible()) m_shaderParamsDialog->reload(); } +void MainWindow::onGotReloadCoreOptions() +{ + if (m_coreOptionsDialog && m_coreOptionsDialog->isVisible()) + m_coreOptionsDialog->reload(); +} + void MainWindow::appendLogMessage(const QString &msg) { emit gotLogMessage(msg); diff --git a/ui/drivers/ui_qt.cpp b/ui/drivers/ui_qt.cpp index 16d49d632e..1c494f1e99 100644 --- a/ui/drivers/ui_qt.cpp +++ b/ui/drivers/ui_qt.cpp @@ -329,6 +329,7 @@ static void* ui_companion_qt_init(void) QObject::connect(viewClosedDocksMenu, SIGNAL(aboutToShow()), mainwindow, SLOT(onViewClosedDocksAboutToShow())); + viewMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CORE_OPTIONS), mainwindow, SLOT(onCoreOptionsClicked())); viewMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SHADER_OPTIONS), mainwindow, SLOT(onShaderParamsClicked())); viewMenu->addSeparator(); diff --git a/ui/drivers/ui_qt.h b/ui/drivers/ui_qt.h index 323c25b039..0084890e88 100644 --- a/ui/drivers/ui_qt.h +++ b/ui/drivers/ui_qt.h @@ -86,6 +86,7 @@ class ThumbnailWidget; class ThumbnailLabel; class FlowLayout; class ShaderParamsDialog; +class CoreOptionsDialog; class CoreInfoDialog; class PlaylistEntryDialog; class ViewOptionsDialog; @@ -297,6 +298,7 @@ signals: void gotStatusMessage(QString msg, unsigned priority, unsigned duration, bool flush); void gotReloadPlaylists(); void gotReloadShaderParams(); + void gotReloadCoreOptions(); void showErrorMessageDeferred(QString msg); void showInfoMessageDeferred(QString msg); void extractArchiveDeferred(QString path, QString extractionDir, QString tempExtension, retro_task_callback_t cb); @@ -330,6 +332,7 @@ public slots: void deferReloadPlaylists(); void onGotReloadPlaylists(); void onGotReloadShaderParams(); + void onGotReloadCoreOptions(); void showWelcomeScreen(); void onIconViewClicked(); void onListViewClicked(); @@ -378,6 +381,7 @@ private slots: void onGridItemClicked(ThumbnailWidget *thumbnailWidget = NULL); void onPlaylistFilesDropped(QStringList files); void onShaderParamsClicked(); + void onCoreOptionsClicked(); void onShowErrorMessage(QString msg); void onShowInfoMessage(QString msg); void onContributorsClicked(); @@ -486,6 +490,7 @@ private: PlaylistEntryDialog *m_playlistEntryDialog; QElapsedTimer m_statusMessageElapsedTimer; QPointer m_shaderParamsDialog; + QPointer m_coreOptionsDialog; QNetworkAccessManager *m_networkManager; QProgressDialog *m_updateProgressDialog;