all repos — mgba @ d2016e382a49dd79d46477902308ec46726b496a

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