swift
swiftlauncher.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2015 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
4 #include "swiftlauncher.h"
5 
6 #include <qcompilerdetection.h>
7 
8 #include <QBitmap>
9 #include <QDesktopServices>
10 #include <QMessageBox>
11 #include <QPixmap>
12 #include <QPointer>
13 #include <QProcess>
14 #include <QPushButton>
15 #include <QShortcut>
16 #include <QStringBuilder>
17 #include <QTimer>
18 
19 #include "ui_swiftlauncher.h"
20 
21 #include "config/buildconfig.h"
24 #include "core/setupreader.h"
27 #include "gui/guiapplication.h"
29 #include "gui/stylesheetutility.h"
30 #include "misc/dbusserver.h"
31 #include "misc/directoryutils.h"
32 #include "misc/icons.h"
33 #include "misc/loghandler.h"
34 #include "misc/logmessage.h"
38 #include "misc/swiftdirectories.h"
39 #include "sound/audioutilities.h"
40 
41 using namespace swift::config;
42 using namespace swift::gui;
43 using namespace swift::gui::components;
44 using namespace swift::core;
45 using namespace swift::core::context;
46 using namespace swift::core::data;
47 using namespace swift::sound;
48 using namespace swift::misc;
49 using namespace swift::misc::db;
50 using namespace swift::misc::network;
51 using namespace swift::misc::simulation;
52 using namespace swift::misc::simulation::data;
53 using namespace swift::misc::simulation::fscommon;
54 
55 CSwiftLauncher::CSwiftLauncher(bool installerMode, QWidget *parent)
56  : QMainWindow(parent, CEnableForFramelessWindow::modeToWindowFlags(CEnableForFramelessWindow::WindowNormal)),
57  CEnableForFramelessWindow(CEnableForFramelessWindow::WindowFrameless, true, "framelessMainWindow", this),
59 {
60  Q_ASSERT_X(sGui, Q_FUNC_INFO, "Need sGui");
62  ui->setupUi(this);
63  this->init(); // reads also defaults from settings
64 
65  connect(ui->tb_SwiftCore, &QPushButton::pressed, this, &CSwiftLauncher::startButtonPressed);
66  connect(ui->tb_SwiftMappingTool, &QPushButton::pressed, this, &CSwiftLauncher::startButtonPressed);
67  connect(ui->tb_SwiftGui, &QPushButton::pressed, this, &CSwiftLauncher::startButtonPressed);
68  connect(ui->tb_Database, &QPushButton::pressed, this, &CSwiftLauncher::startButtonPressed);
69  connect(ui->tb_BackToMain, &QToolButton::pressed, this, &CSwiftLauncher::showMainPage);
70  connect(ui->tb_ConfigurationWizard, &QToolButton::pressed, this, &CSwiftLauncher::startWizard);
71  connect(ui->tb_Launcher, &QToolBox::currentChanged, this, &CSwiftLauncher::tabChanged);
72 
73  connect(ui->rb_SwiftDistributed, &QRadioButton::released, this, &CSwiftLauncher::onCoreModeReleased,
75  connect(ui->rb_SwiftStandalone, &QRadioButton::released, this, &CSwiftLauncher::onCoreModeReleased,
77 
78  connect(ui->comp_UpdateInfo, &CUpdateInfoComponent::updateInfoAvailable, this, &CSwiftLauncher::updateInfoAvailable,
80  connect(ui->comp_UpdateInfo, &CUpdateInfoComponent::newerPilotClientAvailable, this, &CSwiftLauncher::setHeaderInfo,
82  connect(ui->comp_DBusSelector, &CDBusServerAddressSelector::editingFinished, this,
83  &CSwiftLauncher::onDBusEditingFinished, Qt::QueuedConnection);
84  connect(sGui, &CGuiApplication::styleSheetsChanged, this, &CSwiftLauncher::onStyleSheetsChanged,
86 
87  connect(ui->pb_LogDir, &QPushButton::released, sGui, &CGuiApplication::openStandardLogDirectory,
89  connect(ui->pb_DumpDir, &QPushButton::released, sGui, &CGuiApplication::openStandardCrashDumpDirectory,
91  connect(ui->pb_Log, &QPushButton::released, this, &CSwiftLauncher::showLogPage, Qt::QueuedConnection);
92  connect(ui->pb_Log, &QPushButton::released, this, &CSwiftLauncher::showLogPage, Qt::QueuedConnection);
93  connect(ui->pb_FSXConfigDirs, &QPushButton::released, this, &CSwiftLauncher::showSimulatorConfigDirs,
95  connect(ui->pb_P3DConfigDirs, &QPushButton::released, this, &CSwiftLauncher::showSimulatorConfigDirs,
97 
98  const QShortcut *logPageShortCut =
99  new QShortcut(QKeySequence(static_cast<Qt::Key>(Qt::CTRL) + Qt::Key_L), this, SLOT(showLogPage()));
100  Q_UNUSED(logPageShortCut)
101 
102  // periodically check
103  connect(&m_checkTimer, &QTimer::timeout, this, &CSwiftLauncher::checkRunningApplicationsAndCore);
104  m_checkTimer.setInterval(2500);
105  m_checkTimer.start();
106 
107  // platform specific tool
108  ui->gb_ToolsWindows->setEnabled(CBuildConfig::isRunningOnWindowsNtPlatform());
109  if (CBuildConfig::isRunningOnWindowsNtPlatform())
110  {
111  connect(ui->pb_ClearRegistry, &QPushButton::released, this, &CSwiftLauncher::clearWindowsRegistry);
112  }
113 
114  const QPointer<CSwiftLauncher> myself(this);
115  if (installerMode)
116  {
117  QTimer::singleShot(1000, this, [=] {
118  if (!sGui || sGui->isShuttingDown() || !myself) { return; }
119  ui->fr_SwiftLauncherMain->showOverlayHTMLMessage("Checking installation!<br>One moment please ....");
120  this->raise();
121  });
122  }
123 
124  // auto launch wizard and other init parts
125  QTimer::singleShot(2500, this, [=] {
126  if (!sGui || sGui->isShuttingDown() || !myself) { return; }
127  this->onCoreModeReleased();
128  this->requestMacMicrophoneAccess();
129  if (installerMode) this->installerMode();
130  });
131 
132  this->show();
133 }
134 
135 void CSwiftLauncher::installerMode()
136 {
137  if (!sGui || sGui->isShuttingDown()) { return; }
138 
139  bool runDialog = false;
140  do {
141  const QDir dir = CSwiftDirectories::logDirectory();
142  if (!dir.exists()) { break; }
143 
144  for (const CSimulatorInfo &sim : CSimulatorInfo::allSimulatorsSet())
145  {
146  this->synchronizeCache(sim);
147  const int c = this->getCachedModelsCount(sim);
148  if (c > 0)
149  {
150  // we already have data
151  runDialog = true;
152  break;
153  }
154  }
155  }
156  while (false);
157 
158  bool startWizard = true;
159  ui->fr_SwiftLauncherMain->closeOverlay();
160 
161  if (runDialog)
162  {
163  const QMessageBox::StandardButton ret =
164  QMessageBox::question(this, tr("swift configuration"),
165  tr("This installation directory already contains a swift configuration.\n"
166  "Do you want to use that one?"));
167  if (ret != QMessageBox::No) { startWizard = false; }
168  }
169 
170  if (startWizard) { this->startWizard(); }
171 }
172 
173 void CSwiftLauncher::clearWindowsRegistry()
174 {
175  if (!CBuildConfig::isRunningOnWindowsNtPlatform()) { return; }
176  const QMessageBox::StandardButton ret =
177  QMessageBox::warning(this, tr("Registry swift applications"),
178  tr("Do you really want to delete all entries?\nThis cannot be undone!"),
180  if (ret != QMessageBox::Yes) { return; }
181  CGuiApplication::removeAllWindowsSwiftRegistryEntries();
182 }
183 
185 
186 QString CSwiftLauncher::getCmdLine() const { return this->toCmdLine(m_executable, m_executableArgs); }
187 
189 {
190  if (m_executable.isEmpty()) { return false; }
191  const QString cmd = this->getCmdLine();
192  CLogMessage(this).info(cmd);
193  return QProcess::startDetached(m_executable, m_executableArgs);
194 }
195 
196 CEnableForFramelessWindow::WindowMode CSwiftLauncher::getWindowMode() const
197 {
198  if (ui->rb_WindowFrameless->isChecked()) { return CEnableForFramelessWindow::WindowFrameless; }
199  return CEnableForFramelessWindow::WindowNormal;
200 }
201 
202 CoreModes::CoreMode CSwiftLauncher::getCoreMode() const
203 {
204  if (ui->rb_SwiftStandalone->isChecked()) { return CoreModes::Standalone; }
205  if (ui->rb_SwiftDistributed->isChecked()) { return CoreModes::Distributed; }
206 
207  Q_ASSERT_X(false, Q_FUNC_INFO, "wrong mode");
208  return CoreModes::Standalone;
209 }
210 
212 {
214 }
215 
217 {
219 }
220 
222 {
225 }
226 
227 void CSwiftLauncher::updateInfoAvailable()
228 {
229  this->setHeaderInfo(ui->comp_UpdateInfo->getLatestAvailablePilotClientArtifactForSelection());
230 }
231 
232 void CSwiftLauncher::init()
233 {
234  Q_ASSERT_X(sGui, Q_FUNC_INFO, "Need sGui");
236 
237  m_mwaOverlayFrame = ui->fr_SwiftLauncherMain;
238  m_mwaStatusBar = nullptr;
239  m_mwaLogComponent = ui->comp_SwiftLauncherLog;
240 
241  this->initStyleSheet();
242  this->initLogDisplay();
243  this->setDefaults();
244 
245  ui->lbl_HeaderInfo->setVisible(false);
246  ui->sw_SwiftLauncher->setCurrentWidget(ui->pg_SwiftLauncherMain);
247  ui->tb_Launcher->setCurrentWidget(ui->pg_CoreMode);
248 }
249 
250 void CSwiftLauncher::initStyleSheet()
251 {
252  if (!sGui || sGui->isShuttingDown()) { return; }
253  const QString s = sGui->getStyleSheetUtility().styles({ CStyleSheetUtility::fileNameFonts(),
254  CStyleSheetUtility::fileNameStandardWidget(),
255  CStyleSheetUtility::fileNameSwiftLauncher() });
256  this->setStyleSheet(""); // clear, otherwise launcher crashing
257  this->setStyleSheet(s);
258 }
259 
260 void CSwiftLauncher::initLogDisplay()
261 {
262  CLogHandler::instance()->install(true);
263  CLogHandler::instance()->enableConsoleOutput(false); // default disable
264 
265  ui->comp_SwiftLauncherLog->showFilterBar();
266  ui->comp_SwiftLauncherLog->filterUseRadioButtonDescriptiveIcons(false);
267 
268  m_logHistory.setFilter(CLogPattern().withSeverity(CStatusMessage::SeverityError));
269  connect(&m_logHistory, &CLogHistoryReplica::elementAdded, this,
270  qOverload<const CStatusMessage &>(&CSwiftLauncher::showStatusMessage));
271  m_logHistory.initialize(sApp->getDataLinkDBus());
272 }
273 
274 void CSwiftLauncher::setHeaderInfo(const CArtifact &latestArtifact)
275 {
276  const bool isNewer = latestArtifact.isNewerThanCurrentBuild();
277  ui->lbl_HeaderInfo->setVisible(isNewer);
278  if (isNewer)
279  {
280  static const QString t("New version '%1' ['%2'/'%3']");
281  ui->lbl_HeaderInfo->setText(t.arg(latestArtifact.getVersion(), latestArtifact.getPlatform().getPlatformName(),
282  latestArtifact.getMostStableDistribution().getChannel()));
283  ui->lbl_HeaderInfo->setStyleSheet("background: red; color: yellow;");
284  }
285 }
286 
287 bool CSwiftLauncher::setSwiftCoreExecutable()
288 {
289  if (!sGui || sGui->isShuttingDown()) { return false; }
290  this->saveSetup();
291  QStringList args = ui->comp_DBusSelector->getDBusCmdLineArgs();
292  if (ui->cb_ResetWindow->isChecked()) { args.append("--resetsize"); }
293  if (ui->cb_DisableCoreAudio->isChecked()) { args.append("--noaudio"); }
294 
295  m_executableArgs = sGui->argumentsJoined(args);
296  m_executable = CSwiftDirectories::executableFilePath(CBuildConfig::swiftCoreExecutableName());
297  return true;
298 }
299 
300 bool CSwiftLauncher::setSwiftDataExecutable()
301 {
302  m_executable = CSwiftDirectories::executableFilePath(CBuildConfig::swiftDataExecutableName());
303 
304  QStringList fsdArgs;
305 #ifdef SWIFT_VATSIM_SUPPORT
306  int id = 0;
307  QString key;
308  if (IContextNetwork::getCmdLineClientIdAndKey(id, key))
309  {
310  // from cmd. line
311  fsdArgs << "--idAndKey";
312  fsdArgs << sApp->getParserValue("clientIdAndKey"); // as typed in
313  }
314 #endif
315 
316  m_executableArgs = sGui->argumentsJoined({}, fsdArgs);
317  return true;
318 }
319 
320 bool CSwiftLauncher::setSwiftGuiExecutable()
321 {
322  if (!sGui || sGui->isShuttingDown()) { return false; }
323  m_executable = CSwiftDirectories::executableFilePath(CBuildConfig::swiftGuiExecutableName());
324  QStringList args { "--core", CoreModes::coreModeToString(getCoreMode()), "--window",
325  CEnableForFramelessWindow::windowModeToString(getWindowMode()) };
326 
327  if (ui->cb_ResetWindow->isChecked()) { args << "--resetsize"; }
328  if (this->isStandaloneGuiSelected())
329  {
330  if (ui->cb_DisableSaAfv->isChecked()) { args.append("--noaudio"); }
331  }
332  else
333  {
334  if (ui->cb_DisableGUIAfv->isChecked()) { args.append("--noaudio"); }
335 
336  const QString dBus(ui->comp_DBusSelector->getDBusAddress());
337  args.append(ui->comp_DBusSelector->getDBusCmdLineArgs());
338  this->saveSetup();
339 
340  QString msg;
341  if (!CSwiftLauncher::canConnectSwiftOnDBusServer(dBus, msg))
342  {
343  const CStatusMessage m(this, CStatusMessage::SeverityError,
344  "DBus server for '" + dBus + "' can not be connected.\n" +
345  "Likely the core is not running or is not reachable.\n" + "Details: " + msg,
346  true);
347  this->showStatusMessage(m);
348  return false;
349  }
350  }
351  this->saveSetup();
352  m_executableArgs = sGui->argumentsJoined(args);
353  return true;
354 }
355 
356 bool CSwiftLauncher::canConnectSwiftOnDBusServer(const QString &dBusAddress, QString &msg) const
357 {
358  if (this->isStandaloneGuiSelected()) { return true; } // do not mind here
359  return CContextApplicationProxy::isContextResponsive(dBusAddress, msg);
360 }
361 
362 bool CSwiftLauncher::isStandaloneGuiSelected() const { return ui->rb_SwiftStandalone->isChecked(); }
363 
364 void CSwiftLauncher::setDefaults()
365 {
366  const CLauncherSetup setup(m_setup.get());
367  const QString dbus(setup.getDBusAddress().toLower().trimmed());
368  ui->comp_DBusSelector->set(dbus);
369 
370  ui->rb_WindowFrameless->setChecked(setup.useFramelessWindow());
371  ui->rb_WindowNormal->setChecked(!setup.useFramelessWindow());
372 
373  const CLauncherSetup::CoreMode mode = setup.getCoreMode();
374  ui->rb_SwiftStandalone->setChecked(mode == CLauncherSetup::Standalone ? true : false);
375  ui->rb_SwiftDistributed->setChecked(mode == CLauncherSetup::Distributed ? true : false);
376 
377  const CLauncherSetup::AudioMode audio = setup.getAudioMode();
378  ui->cb_DisableCoreAudio->setChecked(audio.testFlag(CLauncherSetup::AudioDisableDistributedCoreAudio));
379  ui->cb_DisableGUIAfv->setChecked(audio.testFlag(CLauncherSetup::AudioDisableDistributedGuiAudio));
380  ui->cb_DisableSaAfv->setChecked(audio.testFlag(CLauncherSetup::AudioDisableStandaloneAudio));
381 }
382 
383 void CSwiftLauncher::saveSetup()
384 {
385  CLauncherSetup setup = m_setup.get();
386  const QString dBus(ui->comp_DBusSelector->getDBusAddress());
387  if (!dBus.isEmpty()) { setup.setDBusAddress(dBus); }
388  setup.setFramelessWindow(ui->rb_WindowFrameless->isChecked());
389  setup.setCoreMode(CLauncherSetup::Standalone);
390 
391  CLauncherSetup::AudioMode audio = CLauncherSetup::AudioNothingDisabled;
392  audio.setFlag(CLauncherSetup::AudioDisableDistributedCoreAudio, ui->cb_DisableCoreAudio->isChecked());
393  audio.setFlag(CLauncherSetup::AudioDisableDistributedGuiAudio, ui->cb_DisableGUIAfv->isChecked());
394  audio.setFlag(CLauncherSetup::AudioDisableStandaloneAudio, ui->cb_DisableSaAfv->isChecked());
395  setup.setAudioMode(audio);
396 
397  if (ui->rb_SwiftDistributed->isChecked()) { setup.setCoreMode(CLauncherSetup::Distributed); }
398 
399  const CStatusMessage msg = m_setup.set(setup);
400  Q_UNUSED(msg)
401 }
402 
403 bool CSwiftLauncher::warnAboutOtherSwiftApplications()
404 {
405  CApplicationInfoList running = CGuiApplication::getRunningApplications();
406  running.removeApplication(CApplicationInfo::Launcher);
407  if (running.isEmpty()) { return true; }
408 
409  // getting here means another application is running
410  const QString msg = u"While using the wizard no other application should run.\nClose applications and try "
411  u"again.\nCurrently running: " %
412  running.processNames().join(',');
413  QMessageBox::question(this, "Wizard", msg, QMessageBox::StandardButtons(QMessageBox::StandardButton::Close));
414  return false;
415 }
416 
417 QString CSwiftLauncher::toCmdLine(const QString &exe, const QStringList &exeArgs)
418 {
419  if (exeArgs.isEmpty()) { return exe; }
420  const QString exeArgsString = exeArgs.join(' ');
421  const QString cmd(exe + " " + exeArgsString);
422  return cmd;
423 }
424 
425 void CSwiftLauncher::startButtonPressed()
426 {
427  const QObject *sender = QObject::sender();
428 
430  const bool shift = km.testFlag(Qt::ShiftModifier);
431 
432  if (sender == ui->tb_SwiftGui)
433  {
434  if (this->setSwiftGuiExecutable())
435  {
436  if (shift) { this->popupExecutableArgs(); }
437  else { close(); }
438  }
439  }
440  else if (sender == ui->tb_SwiftMappingTool)
441  {
442  ui->tb_SwiftMappingTool->setEnabled(false);
443  m_startMappingToolWaitCycles = 2;
444  if (this->setSwiftDataExecutable())
445  {
446  if (shift) { this->popupExecutableArgs(); }
447  else { close(); }
448  }
449  }
450  else if (sender == ui->tb_SwiftCore)
451  {
452  if (this->isStandaloneGuiSelected()) { ui->rb_SwiftDistributed->setChecked(true); }
453  ui->tb_SwiftCore->setEnabled(false);
454  m_startCoreWaitCycles = 2;
455  if (this->setSwiftCoreExecutable())
456  {
457  if (shift) { this->popupExecutableArgs(); }
458  else { this->startDetached(); }
459  }
460  }
461  else if (sender == ui->tb_Database)
462  {
463  const CUrl homePage(sApp->getGlobalSetup().getDbHomePageUrl());
464  QDesktopServices::openUrl(homePage);
465  }
466 }
467 
468 void CSwiftLauncher::dbusServerModeSelected(bool selected)
469 {
470  if (!selected) { return; }
471  if (!this->isStandaloneGuiSelected()) { return; }
472  ui->rb_SwiftDistributed->setChecked(true);
473 }
474 
475 void CSwiftLauncher::showStatusMessage(const CStatusMessage &msg)
476 {
477  using namespace std::chrono_literals;
478  ui->fr_SwiftLauncherMain->showOverlayMessage(msg, 5s);
479 }
480 
481 void CSwiftLauncher::showStatusMessage(const QString &htmlMsg)
482 {
483  using namespace std::chrono_literals;
484  ui->fr_SwiftLauncherMain->showOverlayMessage(htmlMsg, 5s);
485 }
486 
487 void CSwiftLauncher::showMainPage() { ui->sw_SwiftLauncher->setCurrentWidget(ui->pg_SwiftLauncherMain); }
488 
489 void CSwiftLauncher::tabChanged(int current)
490 {
491  if (current == static_cast<int>(PageUpdates)) { ui->comp_DataUpdates->display(); }
492 }
493 
494 void CSwiftLauncher::showLogPage() { ui->sw_SwiftLauncher->setCurrentWidget(ui->pg_SwiftLauncherLog); }
495 
496 void CSwiftLauncher::checkRunningApplicationsAndCore()
497 {
498  // wait some time before buttons are enabled (allows startup)
499  if (m_startCoreWaitCycles > 0) { m_startCoreWaitCycles--; }
500  if (m_startMappingToolWaitCycles > 0) { m_startMappingToolWaitCycles--; }
501  if (m_startGuiWaitCycles > 0) { m_startGuiWaitCycles--; }
502 
503  const CApplicationInfoList runningApps = sGui->getRunningApplications();
504  const bool foundLocalCore = runningApps.containsApplication(CApplicationInfo::PilotClientCore);
505  const bool foundLocalMappingTool = runningApps.containsApplication(CApplicationInfo::MappingTool);
506  const bool foundLocalPilotClientGui = runningApps.containsApplication(CApplicationInfo::PilotClientGui);
507  const bool standalone = ui->rb_SwiftStandalone->isChecked();
508 
509  ui->tb_SwiftCore->setEnabled(!standalone && !foundLocalCore && m_startCoreWaitCycles < 1);
510  ui->tb_SwiftMappingTool->setEnabled(!foundLocalMappingTool && m_startMappingToolWaitCycles < 1);
511  ui->tb_SwiftGui->setEnabled(!foundLocalPilotClientGui && m_startGuiWaitCycles < 1);
512 }
513 
514 void CSwiftLauncher::startWizard()
515 {
516  const bool show = this->warnAboutOtherSwiftApplications();
517  if (!show) { return; }
518  if (!m_wizard) { m_wizard.reset(new CConfigurationWizard(this)); }
519  m_wizard->show();
520  CGuiUtility::centerWidget(m_wizard.data(), this);
521 }
522 
523 void CSwiftLauncher::onStyleSheetsChanged() { this->initStyleSheet(); }
524 
525 void CSwiftLauncher::onDBusEditingFinished() { ui->rb_SwiftDistributed->setChecked(true); }
526 
527 void CSwiftLauncher::onCoreModeReleased()
528 {
529  const bool sa = ui->rb_SwiftStandalone->isChecked();
530  ui->comp_DBusSelector->setEnabled(!sa);
531  ui->tb_SwiftCore->setEnabled(!sa);
532  ui->gb_AudioSa->setEnabled(sa);
533  ui->gb_AudioDistributed->setEnabled(!sa);
534  this->saveSetup();
535 }
536 
537 void CSwiftLauncher::popupExecutableArgs() { QMessageBox::information(this, "Command line", this->getCmdLine()); }
538 
539 void CSwiftLauncher::showSimulatorConfigDirs()
540 {
541  if (!m_textEditDialog) { m_textEditDialog.reset(new CTextEditDialog(this)); }
542 
543  const QObject *s = QObject::sender();
544  QStringList dirs;
545  QString simDir;
546  QString simObjDir;
547 
548  if (s == ui->pb_P3DConfigDirs)
549  {
550  simDir = CFsDirectories::p3dDir();
551  simObjDir = CFsDirectories::p3dSimObjectsDir();
552  const QString versionHint = CFsDirectories::guessP3DVersion(simDir);
553  dirs = CFsDirectories::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(simObjDir, versionHint);
554  }
555  else if (s == ui->pb_FSXConfigDirs)
556  {
557  dirs = CFsDirectories::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths();
558  simDir = CFsDirectories::fsxDir();
559  simObjDir = CFsDirectories::fsxSimObjectsDir();
560  }
561 
562  const QString info = u"Sim.dir: " % simDir % "\n" % u"Sim.objects: " % simObjDir % "\n" %
563  (dirs.isEmpty() ? "No dirs" : dirs.join("\n"));
564 
565  m_textEditDialog->setReadOnly();
566  m_textEditDialog->textEdit()->setText(info);
567  m_textEditDialog->show();
568 }
569 
570 bool CSwiftLauncher::shouldStartAppDetached() const { return !m_executable.isEmpty(); }
571 
572 void CSwiftLauncher::requestMacMicrophoneAccess()
573 {
574  // needed to be able to start core/GUI which need MIC access
575  // https://discordapp.com/channels/539048679160676382/567983892791951374/634806582013591603
576 #ifdef Q_OS_MAC
577  const CMacOSMicrophoneAccess::AuthorizationStatus status = m_micAccess.getAuthorizationStatus();
578  if (status == CMacOSMicrophoneAccess::Authorized) { return; }
579  m_micAccess.requestAccess();
580  CLogMessage(this).info(u"MacOS requested input device");
581 #endif
582 }
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
Definition: application.cpp:71
swift launcher tool
Definition: swiftlauncher.h:51
virtual void mouseReleaseEvent(QMouseEvent *event)
Mouse events for frameless window.
virtual void mouseMoveEvent(QMouseEvent *event)
Mouse events for frameless window.
virtual ~CSwiftLauncher()
Destructor.
CSwiftLauncher(bool installerMode, QWidget *parent=nullptr)
Constructor.
bool shouldStartAppDetached() const
Check if an app is set that should be started detached.
bool startDetached()
Start currently set application detached.
virtual void mousePressEvent(QMouseEvent *event)
Mouse events for frameless window.
QString getCmdLine() const
Current command line.
QStringList argumentsJoined(const QStringList &newArguments={}, const QStringList &removeArguments={}) const
Current parameters replaced by new arguments without the cmd line argument.
swift::misc::shared_state::CDataLinkDBus * getDataLinkDBus()
Transport mechanism for sharing state between applications.
QString getParserValue(const QString &option) const
Delegates to QCommandLineParser::value.
data::CGlobalSetup getGlobalSetup() const
Global setup.
bool isShuttingDown() const
Is application shutting down?
static swift::misc::CApplicationInfoList getRunningApplications()
Information about all running apps (including this one only if exec() has already been called)
swift::misc::network::CUrl getDbHomePageUrl() const
Home page url.
Definition: globalsetup.cpp:42
void setAudioMode(AudioMode mode)
Audio mode.
Definition: launchersetup.h:71
void setCoreMode(CoreMode mode)
Core mode.
Definition: launchersetup.h:65
void setFramelessWindow(bool frameless)
Frameless window?
Definition: launchersetup.h:77
void setDBusAddress(const QString &dBusAddress)
DBus address.
Definition: launchersetup.h:59
Main window which can be frameless.
bool handleMousePressEvent(QMouseEvent *event)
Mouse press, required for frameless window.
QPoint m_framelessDragPosition
position, if moving is handled with frameless window
bool handleMouseMoveEvent(QMouseEvent *event)
Mouse moving, required for frameless window.
void registerMainApplicationWidget(QWidget *mainWidget)
Register main application window widget if this is known.
const CStyleSheetUtility & getStyleSheetUtility() const
Style sheet handling.
void initMainApplicationWidget(QWidget *mainWidget)
Init the main application window based on information in this application.
QString styles(const QStringList &fileNames) const
Multiple styles concatenated.
CManagedStatusBar * m_mwaStatusBar
status bar if any
components::CLogComponent * m_mwaLogComponent
the log component if any
COverlayMessagesFrame * m_mwaOverlayFrame
overlay messages if any
Configure the most important settings.
List of swift application descriptions.
QStringList processNames() const
Running application names.
bool containsApplication(CApplicationInfo::Application application) const
List containing entry for CApplicationInfo::Application ?
int removeApplication(CApplicationInfo::Application application)
Remove given application.
T get() const
Get a copy of the current value.
Definition: valuecache.h:408
CStatusMessage set(const typename Trait::type &value, qint64 timestamp=0)
Write a new value. Must be called from the thread in which the owner lives.
Definition: datacache.h:350
Base class with a member CIdentifier to be inherited by a class which has an identity in the environm...
Definition: identifiable.h:24
Class for emitting a log message.
Definition: logmessage.h:27
Value class for matching log messages based on their categories.
Definition: logpattern.h:49
AuthorizationStatus
Authorization status.
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
QString getPlatformName() const
Name of platform.
Definition: platform.cpp:53
bool isEmpty() const
Synonym for empty.
Definition: sequence.h:285
Streamable status message, e.g.
Artifacts ("our software" products)
Definition: artifact.h:23
const CPlatform & getPlatform() const
OS.
Definition: artifact.h:89
bool isNewerThanCurrentBuild() const
Newer than the current build.
Definition: artifact.cpp:72
CDistribution getMostStableDistribution() const
Most stable distribution if any.
Definition: artifact.h:101
const QString & getChannel() const
Version channel (Alpha, Beta, Stable ..)
Definition: distribution.h:45
const QString & getVersion() const
Version info.
Definition: datastore.h:48
Value object encapsulating information of a location, kind of simplified CValueObject compliant versi...
Definition: url.h:27
void setFilter(const U &filter)
Set filter to choose list elements.
Definition: listobserver.h:77
virtual void initialize(IDataLink *dataLink)
Subscribe using the given transport mechanism.
Definition: listobserver.h:70
Simple hardcoded info about the corresponding simulator.
Definition: simulatorinfo.h:41
Basically a QObject free (delegate based) version of CCentralMultiSimulatorModelSetCachesProvider.
Definition: modelcaches.h:640
int getCachedModelsCount(const CSimulatorInfo &simulator) const
Look like IMultiSimulatorModelCaches interface.
Definition: modelcaches.h:648
void synchronizeCache(const CSimulatorInfo &simulator)
Look like IMultiSimulatorModelCaches interface.
Definition: modelcaches.h:674
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
Core data traits (aka cached values) and classes.
Backend services of the swift project, like dealing with the network or the simulators.
Definition: actionbind.cpp:7
High level reusable GUI components.
Definition: aboutdialog.cpp:13
GUI related classes.
Free functions in swift::misc.
bool openUrl(const QUrl &url)
bool exists() const const
Qt::KeyboardModifiers queryKeyboardModifiers()
void append(QList< T > &&value)
bool isEmpty() const const
virtual bool event(QEvent *event) override
QMessageBox::StandardButton information(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
QMessageBox::StandardButton question(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
QMessageBox::StandardButton warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * sender() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid)
T * data() const const
void reset(T *other)
bool isEmpty() const const
QString join(QChar separator) const const
QueuedConnection
typedef KeyboardModifiers
void setInterval(int msec)
void start()
void timeout()
void currentChanged(int index)
bool close()
virtual void mouseMoveEvent(QMouseEvent *event)
virtual void mousePressEvent(QMouseEvent *event)
virtual void mouseReleaseEvent(QMouseEvent *event)
void show()
void setStyleSheet(const QString &styleSheet)
CoreMode
Core runs how and where?
Definition: coremodeenums.h:18