all repos — mgba @ 67c3f386a4106d5d3017aea882f64dc0ae94a375

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