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}