mirror of https://github.com/mgba-emu/mgba.git
Qt: Add integrated configuration loader for the menu
This commit is contained in:
parent
19346dff87
commit
8751f5cc0c
|
@ -2,12 +2,76 @@
|
|||
|
||||
#include "GameController.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
|
||||
extern "C" {
|
||||
#include "platform/commandline.h"
|
||||
}
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
ConfigOption::ConfigOption(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void ConfigOption::connect(std::function<void(const QVariant&)> slot) {
|
||||
m_slot = slot;
|
||||
}
|
||||
|
||||
QAction* ConfigOption::addValue(const QString& text, const QVariant& value, QMenu* parent) {
|
||||
QAction* action = new QAction(text, parent);
|
||||
action->setCheckable(true);
|
||||
QObject::connect(action, &QAction::triggered, [this, value]() {
|
||||
emit valueChanged(value);
|
||||
});
|
||||
parent->addAction(action);
|
||||
m_actions.append(qMakePair(action, value));
|
||||
return action;
|
||||
}
|
||||
|
||||
QAction* ConfigOption::addValue(const QString& text, const char* value, QMenu* parent) {
|
||||
return addValue(text, QString(value), parent);
|
||||
}
|
||||
|
||||
QAction* ConfigOption::addBoolean(const QString& text, QMenu* parent) {
|
||||
QAction* action = new QAction(text, parent);
|
||||
action->setCheckable(true);
|
||||
QObject::connect(action, &QAction::triggered, [this, action]() {
|
||||
emit valueChanged(action->isChecked());
|
||||
});
|
||||
parent->addAction(action);
|
||||
m_actions.append(qMakePair(action, true));
|
||||
return action;
|
||||
}
|
||||
|
||||
void ConfigOption::setValue(bool value) {
|
||||
setValue(QVariant(value));
|
||||
}
|
||||
|
||||
void ConfigOption::setValue(int value) {
|
||||
setValue(QVariant(value));
|
||||
}
|
||||
|
||||
void ConfigOption::setValue(unsigned value) {
|
||||
setValue(QVariant(value));
|
||||
}
|
||||
|
||||
void ConfigOption::setValue(const char* value) {
|
||||
setValue(QVariant(QString(value)));
|
||||
}
|
||||
|
||||
void ConfigOption::setValue(const QVariant& value) {
|
||||
QPair<QAction*, QVariant> action;
|
||||
foreach(action, m_actions) {
|
||||
bool signalsEnabled = action.first->blockSignals(true);
|
||||
action.first->setChecked(value == action.second);
|
||||
action.first->blockSignals(signalsEnabled);
|
||||
}
|
||||
m_slot(value);
|
||||
}
|
||||
|
||||
ConfigController::ConfigController(QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_opts()
|
||||
|
@ -16,6 +80,8 @@ ConfigController::ConfigController(QObject* parent)
|
|||
|
||||
m_opts.audioSync = GameController::AUDIO_SYNC;
|
||||
m_opts.videoSync = GameController::VIDEO_SYNC;
|
||||
m_opts.fpsTarget = 60;
|
||||
m_opts.audioBuffers = 768;
|
||||
GBAConfigLoadDefaults(&m_config, &m_opts);
|
||||
GBAConfigLoad(&m_config);
|
||||
GBAConfigMap(&m_config, &m_opts);
|
||||
|
@ -32,20 +98,68 @@ bool ConfigController::parseArguments(GBAArguments* args, int argc, char* argv[]
|
|||
return ::parseArguments(args, &m_config, argc, argv, 0);
|
||||
}
|
||||
|
||||
ConfigOption* ConfigController::addOption(const char* key) {
|
||||
QString optionName(key);
|
||||
|
||||
if (m_optionSet.contains(optionName)) {
|
||||
return m_optionSet[optionName];
|
||||
}
|
||||
ConfigOption* newOption = new ConfigOption(this);
|
||||
m_optionSet[optionName] = newOption;
|
||||
connect(newOption, &ConfigOption::valueChanged, [this, key](const QVariant& value) {
|
||||
setOption(key, value);
|
||||
});
|
||||
return newOption;
|
||||
}
|
||||
|
||||
void ConfigController::updateOption(const char* key) {
|
||||
if (!key) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString optionName(key);
|
||||
|
||||
if (!m_optionSet.contains(optionName)) {
|
||||
return;
|
||||
}
|
||||
m_optionSet[optionName]->setValue(GBAConfigGetValue(&m_config, key));
|
||||
}
|
||||
|
||||
void ConfigController::setOption(const char* key, bool value) {
|
||||
setOption(key, (int) value);
|
||||
ConfigOption* option = m_optionSet[QString(key)];
|
||||
if (option) {
|
||||
option->setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigController::setOption(const char* key, int value) {
|
||||
GBAConfigSetIntValue(&m_config, key, value);
|
||||
ConfigOption* option = m_optionSet[QString(key)];
|
||||
if (option) {
|
||||
option->setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigController::setOption(const char* key, unsigned value) {
|
||||
GBAConfigSetUIntValue(&m_config, key, value);
|
||||
ConfigOption* option = m_optionSet[QString(key)];
|
||||
if (option) {
|
||||
option->setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigController::setOption(const char* key, const char* value) {
|
||||
GBAConfigSetValue(&m_config, key, value);
|
||||
ConfigOption* option = m_optionSet[QString(key)];
|
||||
if (option) {
|
||||
option->setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigController::setOption(const char* key, const QVariant& value) {
|
||||
QString stringValue(value.toString());
|
||||
setOption(key, stringValue.toLocal8Bit().constData());
|
||||
}
|
||||
|
||||
void ConfigController::write() {
|
||||
|
|
|
@ -1,16 +1,50 @@
|
|||
#ifndef QGBA_CONFIG_CONTROLLER
|
||||
#define QGBA_CONFIG_CONTROLLER
|
||||
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
#include <QScopedPointer>
|
||||
#include <QVariant>
|
||||
|
||||
extern "C" {
|
||||
#include "gba-config.h"
|
||||
#include "util/configuration.h"
|
||||
}
|
||||
|
||||
class QAction;
|
||||
class QMenu;
|
||||
|
||||
struct GBAArguments;
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class ConfigOption : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ConfigOption(QObject* parent = nullptr);
|
||||
|
||||
void connect(std::function<void(const QVariant&)>);
|
||||
|
||||
QAction* addValue(const QString& text, const QVariant& value, QMenu* parent = 0);
|
||||
QAction* addValue(const QString& text, const char* value, QMenu* parent = 0);
|
||||
QAction* addBoolean(const QString& text, QMenu* parent = 0);
|
||||
|
||||
public slots:
|
||||
void setValue(bool value);
|
||||
void setValue(int value);
|
||||
void setValue(unsigned value);
|
||||
void setValue(const char* value);
|
||||
void setValue(const QVariant& value);
|
||||
|
||||
signals:
|
||||
void valueChanged(const QVariant& value);
|
||||
|
||||
private:
|
||||
std::function<void(const QVariant&)> m_slot;
|
||||
QList<QPair<QAction*, QVariant>> m_actions;
|
||||
};
|
||||
|
||||
class ConfigController : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -23,17 +57,23 @@ public:
|
|||
const GBAOptions* options() const { return &m_opts; }
|
||||
bool parseArguments(GBAArguments* args, int argc, char* argv[]);
|
||||
|
||||
ConfigOption* addOption(const char* key);
|
||||
void updateOption(const char* key);
|
||||
|
||||
public slots:
|
||||
void setOption(const char* key, bool value);
|
||||
void setOption(const char* key, int value);
|
||||
void setOption(const char* key, unsigned value);
|
||||
void setOption(const char* key, const char* value);
|
||||
void setOption(const char* key, const QVariant& value);
|
||||
|
||||
void write();
|
||||
|
||||
private:
|
||||
GBAConfig m_config;
|
||||
GBAOptions m_opts;
|
||||
|
||||
QMap<QString, ConfigOption*> m_optionSet;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -12,12 +12,12 @@ using namespace QGBA;
|
|||
|
||||
GBAApp::GBAApp(int& argc, char* argv[])
|
||||
: QApplication(argc, argv)
|
||||
, m_window(&m_configController)
|
||||
{
|
||||
QApplication::setApplicationName(PROJECT_NAME);
|
||||
QApplication::setApplicationVersion(PROJECT_VERSION);
|
||||
|
||||
GBAArguments args = {};
|
||||
m_window.setConfig(&m_configController);
|
||||
if (m_configController.parseArguments(&args, argc, argv)) {
|
||||
m_window.argumentsPassed(&args);
|
||||
} else {
|
||||
|
|
|
@ -20,8 +20,8 @@ protected:
|
|||
bool event(QEvent*);
|
||||
|
||||
private:
|
||||
Window m_window;
|
||||
ConfigController m_configController;
|
||||
Window m_window;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -20,12 +20,13 @@ extern "C" {
|
|||
|
||||
using namespace QGBA;
|
||||
|
||||
Window::Window(QWidget* parent)
|
||||
Window::Window(ConfigController* config, QWidget* parent)
|
||||
: QMainWindow(parent)
|
||||
, m_logView(new LogView())
|
||||
, m_stateWindow(nullptr)
|
||||
, m_screenWidget(new WindowBackground())
|
||||
, m_logo(":/res/mgba-1024.png")
|
||||
, m_config(config)
|
||||
#ifdef USE_FFMPEG
|
||||
, m_videoView(nullptr)
|
||||
#endif
|
||||
|
@ -396,27 +397,16 @@ void Window::setupMenu(QMenuBar* menubar) {
|
|||
emulationMenu->addAction(frameAdvance);
|
||||
|
||||
QMenu* target = emulationMenu->addMenu("FPS target");
|
||||
QAction* setTarget = new QAction(tr("15"), emulationMenu);
|
||||
connect(setTarget, &QAction::triggered, [this]() { emit fpsTargetChanged(15); });
|
||||
target->addAction(setTarget);
|
||||
setTarget = new QAction(tr("30"), emulationMenu);
|
||||
connect(setTarget, &QAction::triggered, [this]() { emit fpsTargetChanged(30); });
|
||||
target->addAction(setTarget);
|
||||
setTarget = new QAction(tr("45"), emulationMenu);
|
||||
connect(setTarget, &QAction::triggered, [this]() { emit fpsTargetChanged(45); });
|
||||
target->addAction(setTarget);
|
||||
setTarget = new QAction(tr("60"), emulationMenu);
|
||||
connect(setTarget, &QAction::triggered, [this]() { emit fpsTargetChanged(60); });
|
||||
target->addAction(setTarget);
|
||||
setTarget = new QAction(tr("90"), emulationMenu);
|
||||
connect(setTarget, &QAction::triggered, [this]() { emit fpsTargetChanged(90); });
|
||||
target->addAction(setTarget);
|
||||
setTarget = new QAction(tr("120"), emulationMenu);
|
||||
connect(setTarget, &QAction::triggered, [this]() { emit fpsTargetChanged(120); });
|
||||
target->addAction(setTarget);
|
||||
setTarget = new QAction(tr("240"), emulationMenu);
|
||||
connect(setTarget, &QAction::triggered, [this]() { emit fpsTargetChanged(240); });
|
||||
target->addAction(setTarget);
|
||||
ConfigOption* fpsTargetOption = m_config->addOption("fpsTarget");
|
||||
fpsTargetOption->connect([this](const QVariant& value) { emit fpsTargetChanged(value.toInt()); });
|
||||
fpsTargetOption->addValue(tr("15"), 15, target);
|
||||
fpsTargetOption->addValue(tr("30"), 30, target);
|
||||
fpsTargetOption->addValue(tr("45"), 45, target);
|
||||
fpsTargetOption->addValue(tr("60"), 60, target);
|
||||
fpsTargetOption->addValue(tr("90"), 90, target);
|
||||
fpsTargetOption->addValue(tr("120"), 120, target);
|
||||
fpsTargetOption->addValue(tr("240"), 240, target);
|
||||
m_config->updateOption("fpsTarget");
|
||||
|
||||
emulationMenu->addSeparator();
|
||||
|
||||
|
@ -427,17 +417,15 @@ void Window::setupMenu(QMenuBar* menubar) {
|
|||
connect(turbo, SIGNAL(triggered(bool)), m_controller, SLOT(setTurbo(bool)));
|
||||
emulationMenu->addAction(turbo);
|
||||
|
||||
QAction* videoSync = new QAction(tr("Sync to &video"), emulationMenu);
|
||||
videoSync->setCheckable(true);
|
||||
videoSync->setChecked(m_controller->videoSync());
|
||||
connect(videoSync, SIGNAL(triggered(bool)), m_controller, SLOT(setVideoSync(bool)));
|
||||
emulationMenu->addAction(videoSync);
|
||||
ConfigOption* videoSync = m_config->addOption("videoSync");
|
||||
videoSync->addBoolean(tr("Sync to &video"), emulationMenu);
|
||||
videoSync->connect([this](const QVariant& value) { m_controller->setVideoSync(value.toBool()); });
|
||||
m_config->updateOption("videoSync");
|
||||
|
||||
QAction* audioSync = new QAction(tr("Sync to &audio"), emulationMenu);
|
||||
audioSync->setCheckable(true);
|
||||
audioSync->setChecked(m_controller->audioSync());
|
||||
connect(audioSync, SIGNAL(triggered(bool)), m_controller, SLOT(setAudioSync(bool)));
|
||||
emulationMenu->addAction(audioSync);
|
||||
ConfigOption* audioSync = m_config->addOption("audioSync");
|
||||
audioSync->addBoolean(tr("Sync to &audio"), emulationMenu);
|
||||
audioSync->connect([this](const QVariant& value) { m_controller->setAudioSync(value.toBool()); });
|
||||
m_config->updateOption("audioSync");
|
||||
|
||||
QMenu* videoMenu = menubar->addMenu(tr("&Video"));
|
||||
QMenu* frameMenu = videoMenu->addMenu(tr("Frame size"));
|
||||
|
@ -468,25 +456,23 @@ void Window::setupMenu(QMenuBar* menubar) {
|
|||
frameMenu->addAction(tr("Fullscreen"), this, SLOT(toggleFullScreen()), QKeySequence("Ctrl+F"));
|
||||
|
||||
QMenu* skipMenu = videoMenu->addMenu(tr("Frame&skip"));
|
||||
ConfigOption* skip = m_config->addOption("frameskip");
|
||||
skip->connect([this](const QVariant& value) { m_controller->setFrameskip(value.toInt()); });
|
||||
for (int i = 0; i <= 10; ++i) {
|
||||
QAction* setSkip = new QAction(QString::number(i), skipMenu);
|
||||
connect(setSkip, &QAction::triggered, [this, i]() {
|
||||
m_controller->setFrameskip(i);
|
||||
});
|
||||
skipMenu->addAction(setSkip);
|
||||
skip->addValue(QString::number(i), i, skipMenu);
|
||||
}
|
||||
m_config->updateOption("frameskip");
|
||||
|
||||
QMenu* soundMenu = menubar->addMenu(tr("&Sound"));
|
||||
QMenu* buffersMenu = soundMenu->addMenu(tr("Buffer &size"));
|
||||
QAction* setBuffer = new QAction(tr("512"), buffersMenu);
|
||||
connect(setBuffer, &QAction::triggered, [this]() { emit audioBufferSamplesChanged(512); });
|
||||
buffersMenu->addAction(setBuffer);
|
||||
setBuffer = new QAction(tr("1024"), buffersMenu);
|
||||
connect(setBuffer, &QAction::triggered, [this]() { emit audioBufferSamplesChanged(1024); });
|
||||
buffersMenu->addAction(setBuffer);
|
||||
setBuffer = new QAction(tr("2048"), buffersMenu);
|
||||
connect(setBuffer, &QAction::triggered, [this]() { emit audioBufferSamplesChanged(2048); });
|
||||
buffersMenu->addAction(setBuffer);
|
||||
ConfigOption* buffers = m_config->addOption("audioBuffers");
|
||||
buffers->connect([this](const QVariant& value) { emit audioBufferSamplesChanged(value.toInt()); });
|
||||
buffers->addValue(tr("512"), 512, buffersMenu);
|
||||
buffers->addValue(tr("768"), 768, buffersMenu);
|
||||
buffers->addValue(tr("1024"), 1024, buffersMenu);
|
||||
buffers->addValue(tr("2048"), 2048, buffersMenu);
|
||||
buffers->addValue(tr("4096"), 4096, buffersMenu);
|
||||
m_config->updateOption("audioBuffers");
|
||||
|
||||
QMenu* debuggingMenu = menubar->addMenu(tr("&Debugging"));
|
||||
QAction* viewLogs = new QAction(tr("View &logs..."), debuggingMenu);
|
||||
|
|
|
@ -27,7 +27,7 @@ class Window : public QMainWindow {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Window(QWidget* parent = nullptr);
|
||||
Window(ConfigController* config, QWidget* parent = nullptr);
|
||||
virtual ~Window();
|
||||
|
||||
GameController* controller() { return m_controller; }
|
||||
|
|
Loading…
Reference in New Issue