all repos — mgba @ 99a6db6738c82d1cb286c29a9b431a41cd5ea8ba

mGBA Game Boy Advance Emulator

src/platform/qt/ConfigController.cpp (view raw)

  1/* Copyright (c) 2013-2015 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include "ConfigController.h"
  7
  8#include "CoreController.h"
  9
 10#include <QAction>
 11#include <QDir>
 12#include <QMenu>
 13
 14#include <mgba/feature/commandline.h>
 15
 16using namespace QGBA;
 17
 18ConfigOption::ConfigOption(QObject* parent)
 19	: QObject(parent)
 20{
 21}
 22
 23void ConfigOption::connect(std::function<void(const QVariant&)> slot, QObject* parent) {
 24	m_slots[parent] = slot;
 25	QObject::connect(parent, &QAction::destroyed, [this, slot, parent]() {
 26		m_slots.remove(parent);
 27	});
 28}
 29
 30QAction* ConfigOption::addValue(const QString& text, const QVariant& value, QMenu* parent) {
 31	QAction* action = new QAction(text, parent);
 32	action->setCheckable(true);
 33	QObject::connect(action, &QAction::triggered, [this, value]() {
 34		emit valueChanged(value);
 35	});
 36	QObject::connect(parent, &QAction::destroyed, [this, action, value]() {
 37		m_actions.removeAll(qMakePair(action, value));
 38	});
 39	parent->addAction(action);
 40	m_actions.append(qMakePair(action, value));
 41	return action;
 42}
 43
 44QAction* ConfigOption::addValue(const QString& text, const char* value, QMenu* parent) {
 45	return addValue(text, QString(value), parent);
 46}
 47
 48QAction* ConfigOption::addBoolean(const QString& text, QMenu* parent) {
 49	QAction* action = new QAction(text, parent);
 50	action->setCheckable(true);
 51	QObject::connect(action, &QAction::triggered, [this, action]() {
 52		emit valueChanged(action->isChecked());
 53	});
 54	QObject::connect(parent, &QAction::destroyed, [this, action]() {
 55		m_actions.removeAll(qMakePair(action, 1));
 56	});
 57	parent->addAction(action);
 58	m_actions.append(qMakePair(action, 1));
 59	return action;
 60}
 61
 62void ConfigOption::setValue(bool value) {
 63	setValue(QVariant(value));
 64}
 65
 66void ConfigOption::setValue(int value) {
 67	setValue(QVariant(value));
 68}
 69
 70void ConfigOption::setValue(unsigned value) {
 71	setValue(QVariant(value));
 72}
 73
 74void ConfigOption::setValue(const char* value) {
 75	setValue(QVariant(QString(value)));
 76}
 77
 78void ConfigOption::setValue(const QVariant& value) {
 79	for (QPair<QAction*, QVariant>& action : m_actions) {
 80		bool signalsEnabled = action.first->blockSignals(true);
 81		action.first->setChecked(value == action.second);
 82		action.first->blockSignals(signalsEnabled);
 83	}
 84	for (std::function<void(const QVariant&)>& slot : m_slots.values()) {
 85		slot(value);
 86	}
 87}
 88
 89QString ConfigController::s_configDir;
 90
 91ConfigController::ConfigController(QObject* parent)
 92	: QObject(parent)
 93{
 94	QString fileName = configDir();
 95	fileName.append(QDir::separator());
 96	fileName.append("qt.ini");
 97	m_settings = new QSettings(fileName, QSettings::IniFormat, this);
 98
 99	mCoreConfigInit(&m_config, PORT);
100
101	m_opts.audioSync = CoreController::AUDIO_SYNC;
102	m_opts.videoSync = CoreController::VIDEO_SYNC;
103	m_opts.fpsTarget = 60;
104	m_opts.audioBuffers = 1536;
105	m_opts.sampleRate = 44100;
106	m_opts.volume = 0x100;
107	m_opts.logLevel = mLOG_WARN | mLOG_ERROR | mLOG_FATAL;
108	m_opts.rewindEnable = false;
109	m_opts.rewindBufferCapacity = 300;
110	m_opts.useBios = true;
111	m_opts.suspendScreensaver = true;
112	m_opts.lockAspectRatio = true;
113	mCoreConfigLoad(&m_config);
114	mCoreConfigLoadDefaults(&m_config, &m_opts);
115	mCoreConfigSetDefaultIntValue(&m_config, "sgb.borders", 1);
116	mCoreConfigSetDefaultIntValue(&m_config, "useCgbColors", 1);
117	mCoreConfigMap(&m_config, &m_opts);
118}
119
120ConfigController::~ConfigController() {
121	mCoreConfigDeinit(&m_config);
122	mCoreConfigFreeOpts(&m_opts);
123}
124
125bool ConfigController::parseArguments(mArguments* args, int argc, char* argv[], mSubParser* subparser) {
126	if (::parseArguments(args, argc, argv, subparser)) {
127		mCoreConfigFreeOpts(&m_opts);
128		applyArguments(args, subparser, &m_config);
129		mCoreConfigMap(&m_config, &m_opts);
130		return true;
131	}
132	return false;
133}
134
135ConfigOption* ConfigController::addOption(const char* key) {
136	QString optionName(key);
137
138	if (m_optionSet.contains(optionName)) {
139		return m_optionSet[optionName];
140	}
141	ConfigOption* newOption = new ConfigOption(this);
142	m_optionSet[optionName] = newOption;
143	connect(newOption, &ConfigOption::valueChanged, [this, key](const QVariant& value) {
144		setOption(key, value);
145	});
146	return newOption;
147}
148
149void ConfigController::updateOption(const char* key) {
150	if (!key) {
151		return;
152	}
153
154	QString optionName(key);
155
156	if (!m_optionSet.contains(optionName)) {
157		return;
158	}
159	m_optionSet[optionName]->setValue(mCoreConfigGetValue(&m_config, key));
160}
161
162QString ConfigController::getOption(const char* key, const QVariant& defaultVal) const {
163	const char* val = mCoreConfigGetValue(&m_config, key);
164	if (val) {
165		return QString(val);
166	}
167	return defaultVal.toString();
168}
169
170QString ConfigController::getOption(const QString& key, const QVariant& defaultVal) const {
171	return getOption(key.toUtf8().constData(), defaultVal);
172}
173
174QVariant ConfigController::getQtOption(const QString& key, const QString& group) const {
175	if (!group.isNull()) {
176		m_settings->beginGroup(group);
177	}
178	QVariant value = m_settings->value(key);
179	if (!group.isNull()) {
180		m_settings->endGroup();
181	}
182	return value;
183}
184
185void ConfigController::saveOverride(const Override& override) {
186	override.save(overrides());
187	write();
188}
189
190void ConfigController::setOption(const char* key, bool value) {
191	mCoreConfigSetIntValue(&m_config, key, value);
192	QString optionName(key);
193	if (m_optionSet.contains(optionName)) {
194		m_optionSet[optionName]->setValue(value);
195	}
196}
197
198void ConfigController::setOption(const char* key, int value) {
199	mCoreConfigSetIntValue(&m_config, key, value);
200	QString optionName(key);
201	if (m_optionSet.contains(optionName)) {
202		m_optionSet[optionName]->setValue(value);
203	}
204}
205
206void ConfigController::setOption(const char* key, unsigned value) {
207	mCoreConfigSetUIntValue(&m_config, key, value);
208	QString optionName(key);
209	if (m_optionSet.contains(optionName)) {
210		m_optionSet[optionName]->setValue(value);
211	}
212}
213
214void ConfigController::setOption(const char* key, const char* value) {
215	mCoreConfigSetValue(&m_config, key, value);
216	QString optionName(key);
217	if (m_optionSet.contains(optionName)) {
218		m_optionSet[optionName]->setValue(value);
219	}
220}
221
222void ConfigController::setOption(const char* key, const QVariant& value) {
223	if (value.type() == QVariant::Bool) {
224		setOption(key, value.toBool());
225		return;
226	}
227	QString stringValue(value.toString());
228	setOption(key, stringValue.toUtf8().constData());
229}
230
231void ConfigController::setQtOption(const QString& key, const QVariant& value, const QString& group) {
232	if (!group.isNull()) {
233		m_settings->beginGroup(group);
234	}
235	m_settings->setValue(key, value);
236	if (!group.isNull()) {
237		m_settings->endGroup();
238	}
239}
240
241QList<QString> ConfigController::getMRU() const {
242	QList<QString> mru;
243	m_settings->beginGroup("mru");
244	for (int i = 0; i < MRU_LIST_SIZE; ++i) {
245		QString item = m_settings->value(QString::number(i)).toString();
246		if (item.isNull()) {
247			continue;
248		}
249		mru.append(item);
250	}
251	m_settings->endGroup();
252	return mru;
253}
254
255void ConfigController::setMRU(const QList<QString>& mru) {
256	int i = 0;
257	m_settings->beginGroup("mru");
258	for (const QString& item : mru) {
259		m_settings->setValue(QString::number(i), item);
260		++i;
261		if (i >= MRU_LIST_SIZE) {
262			break;
263		}
264	}
265	m_settings->endGroup();
266}
267
268void ConfigController::write() {
269	mCoreConfigSave(&m_config);
270	m_settings->sync();
271
272	mCoreConfigFreeOpts(&m_opts);
273	mCoreConfigMap(&m_config, &m_opts);
274}
275
276void ConfigController::makePortable() {
277	mCoreConfigMakePortable(&m_config);
278
279	QString fileName(configDir());
280	fileName.append(QDir::separator());
281	fileName.append("qt.ini");
282	QSettings* settings2 = new QSettings(fileName, QSettings::IniFormat, this);
283	for (const auto& key : m_settings->allKeys()) {
284		settings2->setValue(key, m_settings->value(key));
285	}
286	delete m_settings;
287	m_settings = settings2;
288}
289
290const QString& ConfigController::configDir() {
291	if (s_configDir.isNull()) {
292		char path[PATH_MAX];
293		mCoreConfigDirectory(path, sizeof(path));
294		s_configDir = QString::fromUtf8(path);
295	}
296	return s_configDir;
297}