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
14extern "C" {
15#include "gba/supervisor/overrides.h"
16#include "platform/commandline.h"
17}
18
19using namespace QGBA;
20
21ConfigOption::ConfigOption(QObject* parent)
22 : QObject(parent)
23{
24}
25
26void ConfigOption::connect(std::function<void(const QVariant&)> slot, QObject* parent) {
27 m_slots[parent] = slot;
28 QObject::connect(parent, &QAction::destroyed, [this, slot, parent]() {
29 m_slots.remove(parent);
30 });
31}
32
33QAction* ConfigOption::addValue(const QString& text, const QVariant& value, QMenu* parent) {
34 QAction* action = new QAction(text, parent);
35 action->setCheckable(true);
36 QObject::connect(action, &QAction::triggered, [this, value]() {
37 emit valueChanged(value);
38 });
39 QObject::connect(parent, &QAction::destroyed, [this, action, value]() {
40 m_actions.removeAll(qMakePair(action, value));
41 });
42 parent->addAction(action);
43 m_actions.append(qMakePair(action, value));
44 return action;
45}
46
47QAction* ConfigOption::addValue(const QString& text, const char* value, QMenu* parent) {
48 return addValue(text, QString(value), parent);
49}
50
51QAction* ConfigOption::addBoolean(const QString& text, QMenu* parent) {
52 QAction* action = new QAction(text, parent);
53 action->setCheckable(true);
54 QObject::connect(action, &QAction::triggered, [this, action]() {
55 emit valueChanged(action->isChecked());
56 });
57 QObject::connect(parent, &QAction::destroyed, [this, action]() {
58 m_actions.removeAll(qMakePair(action, 1));
59 });
60 parent->addAction(action);
61 m_actions.append(qMakePair(action, 1));
62 return action;
63}
64
65void ConfigOption::setValue(bool value) {
66 setValue(QVariant(value));
67}
68
69void ConfigOption::setValue(int value) {
70 setValue(QVariant(value));
71}
72
73void ConfigOption::setValue(unsigned value) {
74 setValue(QVariant(value));
75}
76
77void ConfigOption::setValue(const char* value) {
78 setValue(QVariant(QString(value)));
79}
80
81void ConfigOption::setValue(const QVariant& value) {
82 QPair<QAction*, QVariant> action;
83 foreach (action, m_actions) {
84 bool signalsEnabled = action.first->blockSignals(true);
85 action.first->setChecked(value == action.second);
86 action.first->blockSignals(signalsEnabled);
87 }
88 std::function<void(const QVariant&)> slot;
89 foreach(slot, m_slots.values()) {
90 slot(value);
91 }
92}
93
94ConfigController::ConfigController(QObject* parent)
95 : QObject(parent)
96 , m_opts()
97{
98 char path[PATH_MAX];
99 GBAConfigDirectory(path, sizeof(path));
100 QString fileName(path);
101 fileName.append(QDir::separator());
102 fileName.append("qt.ini");
103 m_settings = new QSettings(fileName, QSettings::IniFormat, this);
104
105 GBAConfigInit(&m_config, PORT);
106
107 m_opts.audioSync = GameController::AUDIO_SYNC;
108 m_opts.videoSync = GameController::VIDEO_SYNC;
109 m_opts.fpsTarget = 60;
110 m_opts.audioBuffers = 2048;
111 m_opts.volume = GBA_AUDIO_VOLUME_MAX;
112 m_opts.logLevel = GBA_LOG_WARN | GBA_LOG_ERROR | GBA_LOG_FATAL | GBA_LOG_STATUS;
113 m_opts.rewindEnable = false;
114 m_opts.rewindBufferInterval = 0;
115 m_opts.rewindBufferCapacity = 0;
116 m_opts.useBios = true;
117 m_opts.suspendScreensaver = true;
118 GBAConfigLoadDefaults(&m_config, &m_opts);
119 GBAConfigLoad(&m_config);
120 GBAConfigMap(&m_config, &m_opts);
121}
122
123ConfigController::~ConfigController() {
124 GBAConfigDeinit(&m_config);
125 GBAConfigFreeOpts(&m_opts);
126}
127
128bool ConfigController::parseArguments(GBAArguments* args, int argc, char* argv[]) {
129 return ::parseArguments(args, &m_config, argc, argv, 0);
130}
131
132ConfigOption* ConfigController::addOption(const char* key) {
133 QString optionName(key);
134
135 if (m_optionSet.contains(optionName)) {
136 return m_optionSet[optionName];
137 }
138 ConfigOption* newOption = new ConfigOption(this);
139 m_optionSet[optionName] = newOption;
140 connect(newOption, &ConfigOption::valueChanged, [this, key](const QVariant& value) {
141 setOption(key, value);
142 });
143 return newOption;
144}
145
146void ConfigController::updateOption(const char* key) {
147 if (!key) {
148 return;
149 }
150
151 QString optionName(key);
152
153 if (!m_optionSet.contains(optionName)) {
154 return;
155 }
156 m_optionSet[optionName]->setValue(GBAConfigGetValue(&m_config, key));
157}
158
159QString ConfigController::getOption(const char* key) const {
160 return QString(GBAConfigGetValue(&m_config, key));
161}
162
163QVariant ConfigController::getQtOption(const QString& key, const QString& group) const {
164 if (!group.isNull()) {
165 m_settings->beginGroup(group);
166 }
167 QVariant value = m_settings->value(key);
168 if (!group.isNull()) {
169 m_settings->endGroup();
170 }
171 return value;
172}
173
174void ConfigController::saveOverride(const GBACartridgeOverride& override) {
175 GBAOverrideSave(overrides(), &override);
176 write();
177}
178
179void ConfigController::setOption(const char* key, bool value) {
180 GBAConfigSetIntValue(&m_config, key, value);
181 QString optionName(key);
182 if (m_optionSet.contains(optionName)) {
183 m_optionSet[optionName]->setValue(value);
184 }
185}
186
187void ConfigController::setOption(const char* key, int value) {
188 GBAConfigSetIntValue(&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, unsigned value) {
196 GBAConfigSetUIntValue(&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, const char* value) {
204 GBAConfigSetValue(&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 QVariant& value) {
212 if (value.type() == QVariant::Bool) {
213 setOption(key, value.toBool());
214 return;
215 }
216 QString stringValue(value.toString());
217 setOption(key, stringValue.toUtf8().constData());
218}
219
220void ConfigController::setQtOption(const QString& key, const QVariant& value, const QString& group) {
221 if (!group.isNull()) {
222 m_settings->beginGroup(group);
223 }
224 m_settings->setValue(key, value);
225 if (!group.isNull()) {
226 m_settings->endGroup();
227 }
228}
229
230QList<QString> ConfigController::getMRU() const {
231 QList<QString> mru;
232 m_settings->beginGroup("mru");
233 for (int i = 0; i < MRU_LIST_SIZE; ++i) {
234 QString item = m_settings->value(QString::number(i)).toString();
235 if (item.isNull()) {
236 continue;
237 }
238 mru.append(item);
239 }
240 m_settings->endGroup();
241 return mru;
242}
243
244void ConfigController::setMRU(const QList<QString>& mru) {
245 int i = 0;
246 m_settings->beginGroup("mru");
247 for (const QString& item : mru) {
248 m_settings->setValue(QString::number(i), item);
249 ++i;
250 if (i >= MRU_LIST_SIZE) {
251 break;
252 }
253 }
254 m_settings->endGroup();
255}
256
257void ConfigController::write() {
258 GBAConfigSave(&m_config);
259 m_settings->sync();
260}
261
262void ConfigController::makePortable() {
263 GBAConfigMakePortable(&m_config);
264
265 char path[PATH_MAX];
266 GBAConfigDirectory(path, sizeof(path));
267 QString fileName(path);
268 fileName.append(QDir::separator());
269 fileName.append("qt.ini");
270 QSettings* settings2 = new QSettings(fileName, QSettings::IniFormat, this);
271 for (const auto& key : m_settings->allKeys()) {
272 settings2->setValue(key, m_settings->value(key));
273 }
274 delete m_settings;
275 m_settings = settings2;
276}