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}