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