FlightGear next
LaunchConfig.cxx
Go to the documentation of this file.
1#include "LaunchConfig.hxx"
2
3#include <set>
4
5#include <Main/options.hxx>
6#include <simgear/misc/sg_path.hxx>
7
8#include <QSettings>
9#include <QDebug>
10#include <QIODevice>
11#include <QDataStream>
12#include <QClipboard>
13#include <QGuiApplication>
14
15static bool static_enableDownloadDirUI = true;
16static QSettings::Format static_binaryFormat = QSettings::InvalidFormat;
17
18static bool binaryReadFunc(QIODevice &device, QSettings::SettingsMap &map)
19{
20 QDataStream ds(&device);
21 int count;
22 ds >> count;
23 for (int i=0; i < count; ++i) {
24 QString k;
25 QVariant v;
26 ds >> k >> v;
27 map.insert(k, v);
28 }
29
30 return true;
31}
32
33static bool binaryWriteFunc(QIODevice &device, const QSettings::SettingsMap &map)
34{
35 QDataStream ds(&device);
36
37 ds << map.size();
38 Q_FOREACH(QString key, map.keys()) {
39 ds << key << map.value(key);
40 }
41
42 return true;
43}
44
46 QObject(parent)
47{
48 if (static_binaryFormat == QSettings::InvalidFormat) {
49 static_binaryFormat = QSettings::registerFormat("fglaunch",
52 }
53}
54
59
61{
62 m_values.clear();
63}
64
66{
67 const auto extraArgs = extraArgNames();
69 std::for_each(m_values.begin(), m_values.end(),
70 [options, &extraArgs](const Arg& arg)
71 {
72 const auto name = arg.arg.toStdString();
73 if (arg.origin == Launcher) {
74 auto it = extraArgs.find(name);
75 if (it != extraArgs.end()) {
76 return;
77 }
78 }
79 options->addOption(name, arg.value.toStdString());
80 });
81}
82
83std::set<std::string> LaunchConfig::extraArgNames() const
84{
85 // build a set of all the extra args we have defined
86 std::set<std::string> r;
87 for (auto arg : m_values) {
88 // don't override prop: arguments
89 if (arg.arg == "prop") continue;
90
91 // allow some multi-valued arguments
92 if (arg.arg == "fg-scenery")
93 {
94 continue;
95 }
96
97 if (arg.origin == ExtraArgs)
98 r.insert(arg.arg.toStdString());
99 }
100 return r;
101}
102
103void LaunchConfig::setArg(QString name, QString value, Origin origin)
104{
105 m_values.push_back(Arg(name, value, origin));
106}
107
108void LaunchConfig::setArg(const std::string &name, const std::string &value)
109{
110 setArg(QString::fromStdString(name), QString::fromStdString(value), Launcher);
111}
112
113void LaunchConfig::setProperty(QString path, QVariant value, Origin origin)
114{
115 m_values.push_back(Arg("prop", path + "=" + value.toString(), origin));
116}
117
119{
120 m_values.push_back(Arg((value ? "enable-" : "disable-") + name, "", Launcher));
121}
122
124{
125 QString html;
127 if (!commandLineOpts.empty()) {
128 html += tr("<p>Options passed on the command line:</p>\n");
129 html += "<ul>\n";
130 for (auto opt : commandLineOpts) {
131 html += QString("<li>--") + QString::fromStdString(opt) + "</li>\n";
132 }
133 html += "</ul>\n";
134 }
135
136 reset();
137 collect();
138
139 const auto extraArgs = extraArgNames();
140
141 html += tr("<p>Options set in the launcher:</p>\n");
142 html += "<ul>\n";
143 for (auto arg : valuesFromLauncher()) {
144 auto it = extraArgs.find(arg.arg.toStdString());
145 html += "<li>";
146 bool strikeThrough = (it != extraArgs.end());
147 if (strikeThrough) {
148 html += "<i>";
149 }
150 if (arg.value.isEmpty()) {
151 html += QString("--") + arg.arg;
152 } else if (arg.arg == "prop") {
153 html += QString("--") + arg.arg + ":" + arg.value;
154 } else {
155 html += QString("--") + arg.arg + "=" + arg.value;
156 }
157 if (strikeThrough) {
158 html += tr(" (will be skipped due to being specified as an additional argument)") + "</i> ";
159 }
160 html += "</li>\n";
161 }
162 html += "</ul>\n";
163
164 html += tr("<p>Options set as additional arguments:</p>\n");
165 html += "<ul>\n";
166 for (auto arg : valuesFromExtraArgs()) {
167 if (arg.value.isEmpty()) {
168 html += QString("<li>--") + arg.arg + "</li>\n";
169 } else if (arg.arg == "prop") {
170 html += QString("<li>--") + arg.arg + ":" + arg.value + "</li>\n";
171 } else {
172 html += QString("<li>--") + arg.arg + "=" + arg.value + "</li>\n";
173 }
174 }
175 html += "</ul>\n";
176
177 return html;
178}
179
181{
182 if (a.value.isEmpty()) {
183 return "--" + a.arg + " ";
184 } else if (a.arg == "prop") {
185 return "--" + a.arg + ":" + a.value + " ";
186 } else {
187 return "--" + a.arg + "=" + a.value + " ";
188 }
189}
190
192{
193 QString r;
194
195 for (auto opt : flightgear::Options::sharedInstance()->extractOptions()) {
196 r += "--" + QString::fromStdString(opt) + " ";
197 }
198
199 reset();
200 collect();
201 const auto extraArgs = extraArgNames();
202
203 for (auto arg : valuesFromLauncher()) {
204 auto it = extraArgs.find(arg.arg.toStdString());
205 if (it != extraArgs.end()) {
206 continue; // skipped due to extra arg overriding
207 }
208
209 r += formatArgForClipboard(arg);
210 }
211
212 for (auto arg : valuesFromExtraArgs()) {
213 r += formatArgForClipboard(arg);
214 }
215
216 QClipboard *clipboard = QGuiApplication::clipboard();
217 clipboard->setText(r);
218}
219
221{
222 // create settings using default type (INI) and path (inside FG_HOME),
223 // as setup in initQSettings()
224 m_loadSaveSettings.reset(new QSettings);
225 emit save();
226 m_loadSaveSettings->sync();
227 m_loadSaveSettings.reset();
228
229 return true;
230}
231
233{
234 // create settings using default type (INI) and path (inside FG_HOME),
235 // as setup in initQSettings()
236 m_loadSaveSettings.reset(new QSettings);
237 emit restore();
238 emit postRestore();
239 m_loadSaveSettings.reset();
240 return true;
241}
242
244{
245 m_loadSaveSettings.reset(new QSettings(path, static_binaryFormat));
246 emit save();
247 m_loadSaveSettings.reset();
248 return true;
249}
250
252{
253 m_loadSaveSettings.reset(new QSettings(path, static_binaryFormat));
254 emit restore();
255 // some things have an ordering dependency, give them a chance to run
256 // after other settings have been restored (eg, location or aircraft)
257 emit postRestore();
258 m_loadSaveSettings.reset();
259 return true;
260}
261
262QVariant LaunchConfig::getValueForKey(QString group, QString key, QVariant defaultValue) const
263{
264 if (!m_loadSaveSettings) {
265 // becuase we load settings on component completion, we need
266 // to create the default implementation (using the INI file)
267 // on demand
268 m_loadSaveSettings.reset(new QSettings);
269 }
270
271 m_loadSaveSettings->beginGroup(group);
272 auto v = m_loadSaveSettings->value(key, defaultValue);
273 bool convertedOk = v.convert(static_cast<int>(defaultValue.type()));
274 if (!convertedOk) {
275 qWarning() << "type forcing on loaded value failed:" << key << v << v.typeName() << defaultValue;
276 }
277 // qInfo() << Q_FUNC_INFO << key << "value" << v << v.typeName() << convertedOk;
278 return v;
279}
280
281void LaunchConfig::setValueForKey(QString group, QString key, QVariant var)
282{
283 Q_ASSERT(m_loadSaveSettings);
284 m_loadSaveSettings->beginGroup(group);
285 // qInfo() << "saving" << key << "with value" << var << var.typeName();
286 m_loadSaveSettings->setValue(key, var);
287 m_loadSaveSettings->endGroup();
288}
289
291{
292 return QString::fromStdString(flightgear::defaultDownloadDir().utf8Str());
293}
294
299
304
305auto LaunchConfig::values() const -> std::vector<Arg>
306{
307 return m_values;
308}
309
310auto LaunchConfig::valuesFromLauncher() const -> std::vector<Arg>
311{
312 std::vector<Arg> result;
313 std::copy_if(m_values.begin(), m_values.end(), std::back_inserter(result), [](const Arg& a)
314 { return a.origin == Launcher; });
315 return result;
316}
317
318auto LaunchConfig::valuesFromExtraArgs() const -> std::vector<Arg>
319{
320 std::vector<Arg> result;
321 std::copy_if(m_values.begin(), m_values.end(), std::back_inserter(result), [](const Arg& a)
322 { return a.origin == ExtraArgs; });
323 return result;
324}
bool options(int, char **)
Definition JSBSim.cpp:568
static bool static_enableDownloadDirUI
static bool binaryReadFunc(QIODevice &device, QSettings::SettingsMap &map)
static bool binaryWriteFunc(QIODevice &device, const QSettings::SettingsMap &map)
static QSettings::Format static_binaryFormat
static QString formatArgForClipboard(const LaunchConfig::Arg &a)
#define i(x)
Q_INVOKABLE void setValueForKey(QString group, QString key, QVariant var)
void postRestore()
Q_INVOKABLE QString htmlForCommandLine()
QString defaultDownloadDir
std::vector< Arg > values() const
bool saveConfigToINI()
Q_INVOKABLE bool saveConfigToFile(QString path)
bool enableDownloadDirUI
void restore()
void collect()
bool loadConfigFromINI()
static void setEnableDownloadDirUI(bool enableDownloadDirUI)
std::vector< Arg > valuesFromExtraArgs() const
std::vector< Arg > valuesFromLauncher() const
Q_INVOKABLE void setEnableDisableOption(QString name, bool value)
LaunchConfig(QObject *parent=nullptr)
Q_INVOKABLE void setArg(QString name, QString value=QString(), Origin origin=Launcher)
Q_INVOKABLE void copyCommandLine()
Q_INVOKABLE void setProperty(QString path, QVariant value, Origin origin=Launcher)
Q_INVOKABLE bool loadConfigFromFile(QString path)
void applyToOptions() const
Q_INVOKABLE QVariant getValueForKey(QString group, QString key, QVariant defaultValue=QVariant()) const
string_list extractOptions() const
extractOptions - extract the currently set options as a string array.
Definition options.cxx:3490
static Options * sharedInstance()
Definition options.cxx:2345
const char * name
std::vector< std::string > string_list
Definition globals.hxx:36
SGPath defaultDownloadDir()
return the default platform dependant download directory.
Definition options.cxx:3001