swift
Loading...
Searching...
No Matches
copysettingsandcachescomponent.cpp
1// SPDX-FileCopyrightText: Copyright (C) 2018 swift Project Community / Contributors
2// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3
5
6#include <QFileInfo>
7#include <QRegularExpression>
8#include <QStringBuilder>
9
10#include "ui_copysettingsandcachescomponent.h"
11
12#include "gui/guiapplication.h"
13#include "gui/guiutility.h"
15#include "misc/fileutils.h"
16#include "misc/icons.h"
17#include "misc/json.h"
18
19using namespace swift::misc;
20using namespace swift::misc::audio;
21using namespace swift::misc::input;
22using namespace swift::misc::network;
23using namespace swift::misc::network::data;
24using namespace swift::misc::network::settings;
25using namespace swift::misc::settings;
26using namespace swift::misc::simulation::settings;
27using namespace swift::core::audio;
28using namespace swift::core::application;
29using namespace swift::core::data;
30using namespace swift::gui::settings;
31
33{
36 {
37 ui->setupUi(this);
38 this->initAll();
39 this->allCheckBoxesReadOnly();
40 connect(ui->pb_SelectAll, &QPushButton::clicked, this, &CCopySettingsAndCachesComponent::selectAll);
41 connect(ui->pb_DeselectAll, &QPushButton::clicked, this, &CCopySettingsAndCachesComponent::deselectAll);
42 connect(ui->pb_Copy, &QPushButton::clicked, this, &CCopySettingsAndCachesComponent::copy);
43 connect(ui->comp_OtherSwiftVersions, &COtherSwiftVersionsComponent::versionChanged, this,
44 &CCopySettingsAndCachesComponent::onOtherVersionChanged);
45 }
46
48
50 {
51 ui->comp_OtherSwiftVersions->reloadOtherVersionsDeferred(deferMs);
52 }
53
54 void CCopySettingsAndCachesComponent::onOtherVersionChanged(const CApplicationInfo &info)
55 {
56 readOnlyCheckbox(ui->cb_SettingsAudio,
58 readOnlyCheckbox(ui->cb_SettingsAudioInputDevice,
60 readOnlyCheckbox(ui->cb_SettingsAudioOutputDevice, !CCacheSettingsUtils::hasOtherVersionSettingsFile(
61 info, m_settingsAudioOutputDevice.getFilename()));
62
63 readOnlyCheckbox(ui->cb_SettingsNetworkTrafficServers, !CCacheSettingsUtils::hasOtherVersionSettingsFile(
64 info, m_settingsNetworkServers.getFilename()));
65 readOnlyCheckbox(ui->cb_CacheLastNetworkServer,
66 !CCacheSettingsUtils::hasOtherVersionCacheFile(info, m_cacheLastNetworkServer.getFilename()));
67 readOnlyCheckbox(ui->cb_CacheLastVatsimServer,
68 !CCacheSettingsUtils::hasOtherVersionCacheFile(info, m_cacheLastVatsimServer.getFilename()));
69
70 readOnlyCheckbox(ui->cb_SettingsGuiGeneral,
71 !CCacheSettingsUtils::hasOtherVersionSettingsFile(info, m_settingsGuiGeneral.getFilename()));
72 readOnlyCheckbox(ui->cb_SettingsDockWidget,
73 !CCacheSettingsUtils::hasOtherVersionSettingsFile(info, m_settingsDockWidget.getFilename()));
74 readOnlyCheckbox(ui->cb_SettingsViewUpdate,
75 !CCacheSettingsUtils::hasOtherVersionSettingsFile(info, m_settingsViewUpdate.getFilename()));
76
77 readOnlyCheckbox(ui->cb_SettingsEnabledSimulators, !CCacheSettingsUtils::hasOtherVersionSettingsFile(
78 info, m_settingsEnabledSimulators.getFilename()));
79 readOnlyCheckbox(ui->cb_SettingsSimulatorP3D,
80 !CCacheSettingsUtils::hasOtherVersionSettingsFile(info, m_settingsSimulatorP3D.getFilename()));
81 readOnlyCheckbox(ui->cb_SettingsSimulatorXPlane, !CCacheSettingsUtils::hasOtherVersionSettingsFile(
82 info, m_settingsSimulatorXPlane.getFilename()));
83
84 readOnlyCheckbox(ui->cb_SettingsActionHotkeys, !CCacheSettingsUtils::hasOtherVersionSettingsFile(
85 info, m_settingsActionHotkeys.getFilename()));
86 readOnlyCheckbox(ui->cb_SettingsTextMessages,
87 !CCacheSettingsUtils::hasOtherVersionSettingsFile(info, m_settingsTextMessage.getFilename()));
88 readOnlyCheckbox(ui->cb_SettingsDirectories,
90
91 readOnlyCheckbox(ui->cb_SettingsConsolidation, !CCacheSettingsUtils::hasOtherVersionSettingsFile(
92 info, m_settingsConsolidation.getFilename()));
93 readOnlyCheckbox(ui->cb_SettingsModel,
95 }
96
97 void CCopySettingsAndCachesComponent::initAll()
98 {
99 this->initAudio();
100 this->initNetwork();
101 this->initUi();
102 this->initSimulator();
103 this->initMisc();
104 this->initModel();
105 }
106
107 void CCopySettingsAndCachesComponent::initAudio()
108 {
109 ui->cb_SettingsAudio->setText(checkBoxText(TSettings::humanReadable(), true));
110 ui->cb_SettingsAudioInputDevice->setText(checkBoxText(TInputDevice::humanReadable(), true));
111 ui->cb_SettingsAudioOutputDevice->setText(checkBoxText(TOutputDevice::humanReadable(), true));
112 }
113
114 void CCopySettingsAndCachesComponent::initNetwork()
115 {
116 ui->cb_SettingsNetworkTrafficServers->setText(checkBoxText(TTrafficServers::humanReadable(), true));
117 ui->cb_CacheLastNetworkServer->setText(checkBoxText(TLastServer::humanReadable(), false));
118 ui->cb_CacheLastVatsimServer->setText(checkBoxText(TVatsimLastServer::humanReadable(), false));
119 }
120
121 void CCopySettingsAndCachesComponent::initUi()
122 {
123 ui->cb_SettingsGuiGeneral->setText(checkBoxText(TGeneralGui::humanReadable(), true));
124 ui->cb_SettingsDockWidget->setText(checkBoxText(TDockWidget::humanReadable(), true));
125 ui->cb_SettingsViewUpdate->setText(checkBoxText(TViewUpdateSettings::humanReadable(), true));
126 }
127
128 void CCopySettingsAndCachesComponent::initSimulator()
129 {
130 ui->cb_SettingsEnabledSimulators->setText(checkBoxText(TEnabledSimulators::humanReadable(), true));
131 ui->cb_SettingsSimulatorP3D->setText(checkBoxText(TSimulatorP3D::humanReadable(), true));
132 ui->cb_SettingsSimulatorXPlane->setText(checkBoxText(TSimulatorXP::humanReadable(), true));
133 }
134
135 void CCopySettingsAndCachesComponent::initMisc()
136 {
137 ui->cb_SettingsActionHotkeys->setText(checkBoxText(TActionHotkeys::humanReadable(), true));
138 ui->cb_SettingsTextMessages->setText(checkBoxText(TextMessageSettings::humanReadable(), true));
139 ui->cb_SettingsDirectories->setText(checkBoxText(TDirectorySettings::humanReadable(), true));
140 }
141
142 void CCopySettingsAndCachesComponent::initModel()
143 {
144 ui->cb_SettingsModel->setText(checkBoxText(TModel::humanReadable(), true));
145 ui->cb_SettingsConsolidation->setText(checkBoxText(TBackgroundConsolidation::humanReadable(), true));
146 }
147
148 int CCopySettingsAndCachesComponent::copy()
149 {
150 ui->le_Status->clear();
151
152 const CApplicationInfo otherVersionInfo = ui->comp_OtherSwiftVersions->selectedOtherVersion();
153 if (otherVersionInfo.isNull())
154 {
155 return 0;
156 }
157
158 bool success = false;
159 int copied = 0;
160 QString errMsg;
161 ui->le_Status->setText("Starting to copy from '" + otherVersionInfo.toQString(true) + "'");
162
163 // ------- audio -------
164 if (ui->cb_SettingsAudio->isChecked())
165 {
166 const QString joStr =
167 CCacheSettingsUtils::otherVersionSettingsFileContent(otherVersionInfo, m_settingsAudio.getFilename());
168 if (!joStr.isEmpty())
169 {
170 const audio::CSettings audioSettings = audio::CSettings::fromJsonNoThrow(joStr, true, success, errMsg);
171 if (this->parsingMessage(success, errMsg, m_settingsAudio.getKey()))
172 {
173 this->displayStatusMessage(m_settingsAudio.setAndSave(audioSettings),
174 audioSettings.toQString(true));
175 copied++;
176 }
177 }
178 }
179
180 if (ui->cb_SettingsAudioInputDevice->isChecked())
181 {
183 otherVersionInfo, m_settingsAudioInputDevice.getFilename());
184 const QString audioInputSettings = json::firstJsonValueAsString(joStr);
185 if (!audioInputSettings.isEmpty())
186 {
187 this->displayStatusMessage(m_settingsAudioInputDevice.setAndSave(audioInputSettings),
188 audioInputSettings);
189 copied++;
190 }
191 }
192
193 if (ui->cb_SettingsAudioOutputDevice->isChecked())
194 {
196 otherVersionInfo, m_settingsAudioOutputDevice.getFilename());
197 const QString audioOutputSettings = json::firstJsonValueAsString(joStr);
198 if (!audioOutputSettings.isEmpty())
199 {
200 this->displayStatusMessage(m_settingsAudioOutputDevice.setAndSave(audioOutputSettings),
201 audioOutputSettings);
202 copied++;
203 }
204 }
205
206 // ------- directories -------
207 if (ui->cb_SettingsDirectories->isChecked())
208 {
210 otherVersionInfo, m_settingsDirectories.getFilename());
211 if (!joStr.isEmpty())
212 {
213 const CDirectories directories = CDirectories::fromJsonNoThrow(joStr, true, success, errMsg);
214 if (this->parsingMessage(success, errMsg, m_settingsDirectories.getKey()))
215 {
216 this->displayStatusMessage(m_settingsDirectories.setAndSave(directories),
217 directories.toQString(true));
218 }
219 copied++;
220 }
221 }
222
223 // ------- network -------
224 if (ui->cb_SettingsNetworkTrafficServers->isChecked())
225 {
227 otherVersionInfo, m_settingsNetworkServers.getFilename());
228 if (!joStr.isEmpty())
229 {
230 const CServerList networkServers = CServerList::fromJsonNoThrow(joStr, true, success, errMsg);
231 if (this->parsingMessage(success, errMsg, m_settingsNetworkServers.getKey()))
232 {
233 this->displayStatusMessage(m_settingsNetworkServers.setAndSave(networkServers),
234 networkServers.toQString(true));
235 copied++;
236 }
237 }
238 }
239
240 if (ui->cb_CacheLastNetworkServer->isChecked())
241 {
243 otherVersionInfo, m_cacheLastNetworkServer.getFilename());
244 if (!joStr.isEmpty())
245 {
246 const CServer server = CServer::fromJsonNoThrow(joStr, true, success, errMsg);
247 if (this->parsingMessage(success, errMsg, m_cacheLastNetworkServer.getKey()))
248 {
249 this->displayStatusMessage(m_cacheLastNetworkServer.set(server), server.toQString(true));
250 copied++;
251 }
252 }
253 }
254
255 if (ui->cb_CacheLastVatsimServer->isChecked())
256 {
258 otherVersionInfo, m_cacheLastVatsimServer.getFilename());
259 if (!joStr.isEmpty())
260 {
261 const CServer server = CServer::fromJsonNoThrow(joStr, true, success, errMsg);
262 if (this->parsingMessage(success, errMsg, m_cacheLastVatsimServer.getKey()))
263 {
264 this->displayStatusMessage(m_cacheLastVatsimServer.set(server), server.toQString(true));
265 copied++;
266 }
267 }
268 }
269
270 // ------- GUI -------
271 if (ui->cb_SettingsGuiGeneral->isChecked())
272 {
274 otherVersionInfo, m_settingsGuiGeneral.getFilename());
275 if (!joStr.isEmpty())
276 {
277 const CGeneralGuiSettings guiGeneral =
278 CGeneralGuiSettings::fromJsonNoThrow(joStr, true, success, errMsg);
279 this->displayStatusMessage(m_settingsGuiGeneral.setAndSave(guiGeneral), guiGeneral.toQString(true));
280 copied++;
281 }
282 }
283
284 if (ui->cb_SettingsDockWidget->isChecked())
285 {
287 otherVersionInfo, m_settingsDockWidget.getFilename());
288 if (!joStr.isEmpty())
289 {
290 const CDockWidgetSettings dwSettings =
291 CDockWidgetSettings::fromJsonNoThrow(joStr, true, success, errMsg);
292 this->displayStatusMessage(m_settingsDockWidget.setAndSave(dwSettings), dwSettings.toQString(true));
293 copied++;
294 }
295 }
296
297 if (ui->cb_SettingsViewUpdate->isChecked())
298 {
300 otherVersionInfo, m_settingsViewUpdate.getFilename());
301 if (!joStr.isEmpty())
302 {
303 const CViewUpdateSettings viewUpdate =
304 CViewUpdateSettings::fromJsonNoThrow(joStr, true, success, errMsg);
305 this->displayStatusMessage(m_settingsViewUpdate.setAndSave(viewUpdate), viewUpdate.toQString(true));
306 copied++;
307 }
308 }
309
310 // ------- sims -------
311 if (ui->cb_SettingsEnabledSimulators->isChecked())
312 {
314 otherVersionInfo, m_settingsEnabledSimulators.getFilename());
315 if (!joStr.isEmpty())
316 {
317 const QStringList enabledSims = json::firstJsonValueAsStringList(joStr);
318 if (!enabledSims.isEmpty())
319 {
320 this->displayStatusMessage(m_settingsEnabledSimulators.setAndSave(enabledSims),
321 enabledSims.join(", "));
322 copied++;
323 }
324 }
325 }
326
327 if (ui->cb_SettingsSimulatorP3D->isChecked())
328 {
330 otherVersionInfo, m_settingsSimulatorP3D.getFilename());
331 if (!joStr.isEmpty())
332 {
333 const CSimulatorSettings settings = CSimulatorSettings::fromJsonNoThrow(joStr, true, success, errMsg);
334 if (this->parsingMessage(success, errMsg, m_settingsSimulatorP3D.getKey()))
335 {
336 this->displayStatusMessage(m_settingsSimulatorP3D.setAndSave(settings), settings.toQString(true));
337 }
338 copied++;
339 }
340 }
341
342 if (ui->cb_SettingsSimulatorXPlane->isChecked())
343 {
345 otherVersionInfo, m_settingsSimulatorXPlane.getFilename());
346 if (!joStr.isEmpty())
347 {
348 const CSimulatorSettings settings = CSimulatorSettings::fromJsonNoThrow(joStr, true, success, errMsg);
349 if (this->parsingMessage(success, errMsg, m_settingsSimulatorXPlane.getKey()))
350 {
351 this->displayStatusMessage(m_settingsSimulatorXPlane.setAndSave(settings),
352 settings.toQString(true));
353 }
354 copied++;
355 }
356 }
357
358 // ------ model ------
359 if (ui->cb_SettingsModel->isChecked())
360 {
361 const QString joStr =
362 CCacheSettingsUtils::otherVersionSettingsFileContent(otherVersionInfo, m_settingsModel.getFilename());
363 if (!joStr.isEmpty())
364 {
365 const CModelSettings settings = CModelSettings::fromJsonNoThrow(joStr, true, success, errMsg);
366 if (this->parsingMessage(success, errMsg, m_settingsModel.getKey()))
367 {
368 this->displayStatusMessage(m_settingsModel.setAndSave(settings), settings.toQString(true));
369 copied++;
370 }
371 }
372 }
373
374 if (ui->cb_SettingsConsolidation->isChecked())
375 {
377 otherVersionInfo, m_settingsConsolidation.getFilename());
378 if (!joStr.isEmpty())
379 {
380 bool ok = false;
381 const int consolidation = json::firstJsonValueAsInt(joStr, -1, &ok);
382 if (ok)
383 {
384 this->displayStatusMessage(m_settingsConsolidation.setAndSave(consolidation),
385 QString::number(consolidation));
386 copied++;
387 }
388 }
389 }
390
391 // ------ misc -------
392 if (ui->cb_SettingsActionHotkeys->isChecked())
393 {
395 otherVersionInfo, m_settingsActionHotkeys.getFilename());
396 if (!joStr.isEmpty())
397 {
398 CActionHotkeyList hotkeys = CActionHotkeyList::fromJsonNoThrow(joStr, true, success, errMsg);
399 hotkeys.updateToCurrentMachine();
400 if (this->parsingMessage(success, errMsg, m_settingsActionHotkeys.getKey()))
401 {
402 this->displayStatusMessage(m_settingsActionHotkeys.setAndSave(hotkeys), hotkeys.toQString(true));
403 copied++;
404 }
405 }
406 }
407
408 if (ui->cb_SettingsTextMessages->isChecked())
409 {
411 otherVersionInfo, m_settingsTextMessage.getFilename());
412 if (!joStr.isEmpty())
413 {
414 const CTextMessageSettings settings =
415 CTextMessageSettings::fromJsonNoThrow(joStr, true, success, errMsg);
416 if (this->parsingMessage(success, errMsg, m_settingsTextMessage.getKey()))
417 {
418 this->displayStatusMessage(m_settingsTextMessage.setAndSave(settings), settings.toQString(true));
419 copied++;
420 }
421 }
422 }
423
424 if (copied > 0)
425 {
426 const CStatusMessage m = CStatusMessage(this).validationInfo(u"Copied %1 settings") << copied;
427 this->showOverlayHTMLMessage(m);
428 }
429
430 return copied;
431 }
432
433 void CCopySettingsAndCachesComponent::selectAll()
434 {
435 for (QCheckBox *cb : this->checkBoxes())
436 {
437 cb->setChecked(cb->isEnabled());
438 }
439 }
440
441 void CCopySettingsAndCachesComponent::deselectAll()
442 {
443 for (QCheckBox *cb : this->checkBoxes())
444 {
445 cb->setChecked(false);
446 }
447 }
448
449 QList<QCheckBox *> CCopySettingsAndCachesComponent::checkBoxes() const { return this->findChildren<QCheckBox *>(); }
450
451 bool CCopySettingsAndCachesComponent::parsingMessage(bool success, const QString &msg, const QString &value)
452 {
453 if (success)
454 {
455 return true;
456 }
457 const CStatusMessage sm(this, msg);
458 this->displayStatusMessage(sm, value);
459 return false;
460 }
461
462 void CCopySettingsAndCachesComponent::displayStatusMessage(const CStatusMessage &msg, const QString &value)
463 {
464 if (msg.isEmpty())
465 {
466 return;
467 }
468 if (value.isEmpty())
469 {
470 ui->le_Status->setText(msg.getMessage());
471 }
472 else
473 {
474 ui->le_Status->setText(msg.getMessage() % u' ' % value);
475 }
476 if (sGui)
477 {
479 }
480 }
481
482 void CCopySettingsAndCachesComponent::allCheckBoxesReadOnly()
483 {
484 for (QCheckBox *cb : checkBoxes())
485 {
486 readOnlyCheckbox(cb, true);
487 }
488 }
489
490 void CCopySettingsAndCachesComponent::readOnlyCheckbox(QCheckBox *cb, bool readOnly)
491 {
492 Q_ASSERT_X(cb, Q_FUNC_INFO, "need checkbox");
493 CGuiUtility::checkBoxReadOnly(cb, readOnly);
494 if (readOnly)
495 {
496 cb->setChecked(false);
497 }
498 cb->setEnabled(!readOnly);
499 // cb->setIcon(readOnly ? CIcons::cross16() : CIcons::tick16());
500 }
501
502 QString CCopySettingsAndCachesComponent::checkBoxText(const QString &text, bool setting)
503 {
504 return setting ? QStringLiteral("%1 [setting]").arg(text) : QStringLiteral("%1 [cache]").arg(text);
505 }
506
508 {
509 // re-init other versions
510 if (m_copyCachesAndSettings)
511 {
512 m_copyCachesAndSettings->reloadOtherVersions(1000);
513 }
514 }
515
517
518} // namespace swift::gui::components
void processEventsToRefreshGui() const
Allow the GUI to refresh by processing events, call the event loop.
static void checkBoxReadOnly(QCheckBox *checkBox, bool readOnly)
Pseudo readonly state for checkbox.
bool showOverlayHTMLMessage(const QString &htmlMessage, std::chrono::milliseconds timeout=std::chrono::milliseconds(0))
COverlayMessagesFrame(QWidget *parent=nullptr, Qt::WindowFlags f=Qt::WindowFlags())
Constructor.
void versionChanged(const swift::misc::CApplicationInfo &info)
Selection changed.
Description of a swift application.
bool isNull() const
Null object.
static bool hasOtherVersionSettingsFile(const swift::misc::CApplicationInfo &info, const QString &mySettingFile)
Has the settings file for the given other version?
static QString otherVersionSettingsFileContent(const swift::misc::CApplicationInfo &info, const QString &mySettingFile)
Setting JSON object as string.
static QString otherVersionCacheFileContent(const swift::misc::CApplicationInfo &info, const QString &myCacheFile)
Cache JSON object as string.
static bool hasOtherVersionCacheFile(const swift::misc::CApplicationInfo &info, const QString &myCacheFile)
Has the cache file for the given other version?
QString getFilename() const
Return the file that is used for persistence for this value.
Definition datacache.h:376
bool isEmpty() const
Message empty.
QString getFilename() const
Return the file that is used for persistence for this value.
QString getMessage() const
Message.
void updateToCurrentMachine()
Update for my machine.
QString toQString(bool i18n=false) const
Cast as QString.
Definition mixinstring.h:74
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
Core data traits (aka cached values) and classes.
High level reusable GUI components.
Classes related to configuration settings.
Free functions in swift::misc.
void setChecked(bool)
void clicked(bool checked)
bool isEmpty() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QList< T > findChildren(QAnyStringView name, Qt::FindChildOptions options) const const
QObject * parent() const const
bool isEmpty() const const
QString number(double n, char format, int precision)
QString join(QChar separator) const const
QWidget(QWidget *parent, Qt::WindowFlags f)
void setEnabled(bool)
static const QString & humanReadable()
Optional human readable name.
static const QString & humanReadable()
Optional human readable name.
static const QString & humanReadable()
Optional human readable name.
static const QString & humanReadable()
Optional human readable name.
static const QString & humanReadable()
Optional human readable name.
static const QString & humanReadable()
Optional human readable name.
Definition guisettings.h:89
static const QString & humanReadable()
Optional human readable name.
static const QString & humanReadable()
Optional human readable name.
Definition guisettings.h:75
static const QString & humanReadable()
Optional human readable name.
static const QString & humanReadable()
Optional human readable name.
static const QString & humanReadable()
Optional human readable name.
static const QString & humanReadable()
Definition lastserver.h:25
static const QString & humanReadable()
Optional human readable name.
static const QString & humanReadable()
Optional human readable name.
static const QString & humanReadable()
Optional human readable name.
static const QString & humanReadable()
Optional human readable name.
static const QString & humanReadable()
Optional human readable name.