all repos — mgba @ 609d5314ec8090c5ede27cb07d0d1569463a570a

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