6 #include <qcompilerdetection.h>
9 #include <QDesktopServices>
10 #include <QMessageBox>
14 #include <QPushButton>
16 #include <QStringBuilder>
19 #include "ui_swiftlauncher.h"
41 using namespace swift::config;
45 using namespace swift::core::context;
47 using namespace swift::sound;
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;
60 Q_ASSERT_X(
sGui, Q_FUNC_INFO,
"Need sGui");
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,
84 connect(
sGui, &CGuiApplication::styleSheetsChanged,
this, &CSwiftLauncher::onStyleSheetsChanged,
100 Q_UNUSED(logPageShortCut)
105 m_checkTimer.
start();
108 ui->gb_ToolsWindows->setEnabled(CBuildConfig::isRunningOnWindowsNtPlatform());
109 if (CBuildConfig::isRunningOnWindowsNtPlatform())
119 ui->fr_SwiftLauncherMain->showOverlayHTMLMessage(
"Checking installation!<br>One moment please ....");
127 this->onCoreModeReleased();
128 this->requestMacMicrophoneAccess();
129 if (installerMode) this->installerMode();
135 void CSwiftLauncher::installerMode()
139 bool runDialog =
false;
141 const QDir dir = CSwiftDirectories::logDirectory();
142 if (!dir.
exists()) {
break; }
144 for (
const CSimulatorInfo &sim : CSimulatorInfo::allSimulatorsSet())
158 bool startWizard =
true;
159 ui->fr_SwiftLauncherMain->closeOverlay();
165 tr(
"This installation directory already contains a swift configuration.\n"
166 "Do you want to use that one?"));
170 if (startWizard) { this->startWizard(); }
173 void CSwiftLauncher::clearWindowsRegistry()
175 if (!CBuildConfig::isRunningOnWindowsNtPlatform()) {
return; }
178 tr(
"Do you really want to delete all entries?\nThis cannot be undone!"),
181 CGuiApplication::removeAllWindowsSwiftRegistryEntries();
190 if (m_executable.
isEmpty()) {
return false; }
198 if (ui->rb_WindowFrameless->isChecked()) {
return CEnableForFramelessWindow::WindowFrameless; }
199 return CEnableForFramelessWindow::WindowNormal;
204 if (ui->rb_SwiftStandalone->isChecked()) {
return CoreModes::Standalone; }
205 if (ui->rb_SwiftDistributed->isChecked()) {
return CoreModes::Distributed; }
207 Q_ASSERT_X(
false, Q_FUNC_INFO,
"wrong mode");
208 return CoreModes::Standalone;
227 void CSwiftLauncher::updateInfoAvailable()
229 this->setHeaderInfo(ui->comp_UpdateInfo->getLatestAvailablePilotClientArtifactForSelection());
232 void CSwiftLauncher::init()
234 Q_ASSERT_X(
sGui, Q_FUNC_INFO,
"Need sGui");
241 this->initStyleSheet();
242 this->initLogDisplay();
245 ui->lbl_HeaderInfo->setVisible(
false);
246 ui->sw_SwiftLauncher->setCurrentWidget(ui->pg_SwiftLauncherMain);
247 ui->tb_Launcher->setCurrentWidget(ui->pg_CoreMode);
250 void CSwiftLauncher::initStyleSheet()
254 CStyleSheetUtility::fileNameStandardWidget(),
255 CStyleSheetUtility::fileNameSwiftLauncher() });
260 void CSwiftLauncher::initLogDisplay()
262 CLogHandler::instance()->install(
true);
263 CLogHandler::instance()->enableConsoleOutput(
false);
265 ui->comp_SwiftLauncherLog->showFilterBar();
266 ui->comp_SwiftLauncherLog->filterUseRadioButtonDescriptiveIcons(
false);
269 connect(&m_logHistory, &CLogHistoryReplica::elementAdded,
this,
270 qOverload<const CStatusMessage &>(&CSwiftLauncher::showStatusMessage));
274 void CSwiftLauncher::setHeaderInfo(
const CArtifact &latestArtifact)
277 ui->lbl_HeaderInfo->setVisible(isNewer);
280 static const QString t(
"New version '%1' ['%2'/'%3']");
283 ui->lbl_HeaderInfo->setStyleSheet(
"background: red; color: yellow;");
287 bool CSwiftLauncher::setSwiftCoreExecutable()
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"); }
296 m_executable = CSwiftDirectories::executableFilePath(CBuildConfig::swiftCoreExecutableName());
300 bool CSwiftLauncher::setSwiftDataExecutable()
302 m_executable = CSwiftDirectories::executableFilePath(CBuildConfig::swiftDataExecutableName());
305 #ifdef SWIFT_VATSIM_SUPPORT
308 if (IContextNetwork::getCmdLineClientIdAndKey(
id, key))
311 fsdArgs <<
"--idAndKey";
320 bool CSwiftLauncher::setSwiftGuiExecutable()
323 m_executable = CSwiftDirectories::executableFilePath(CBuildConfig::swiftGuiExecutableName());
324 QStringList args {
"--core", CoreModes::coreModeToString(getCoreMode()),
"--window",
325 CEnableForFramelessWindow::windowModeToString(getWindowMode()) };
327 if (ui->cb_ResetWindow->isChecked()) { args <<
"--resetsize"; }
328 if (this->isStandaloneGuiSelected())
330 if (ui->cb_DisableSaAfv->isChecked()) { args.
append(
"--noaudio"); }
334 if (ui->cb_DisableGUIAfv->isChecked()) { args.
append(
"--noaudio"); }
336 const QString dBus(ui->comp_DBusSelector->getDBusAddress());
337 args.
append(ui->comp_DBusSelector->getDBusCmdLineArgs());
341 if (!CSwiftLauncher::canConnectSwiftOnDBusServer(dBus, msg))
344 "DBus server for '" + dBus +
"' can not be connected.\n" +
345 "Likely the core is not running or is not reachable.\n" +
"Details: " + msg,
347 this->showStatusMessage(m);
356 bool CSwiftLauncher::canConnectSwiftOnDBusServer(
const QString &dBusAddress,
QString &msg)
const
358 if (this->isStandaloneGuiSelected()) {
return true; }
359 return CContextApplicationProxy::isContextResponsive(dBusAddress, msg);
362 bool CSwiftLauncher::isStandaloneGuiSelected()
const {
return ui->rb_SwiftStandalone->isChecked(); }
364 void CSwiftLauncher::setDefaults()
367 const QString dbus(setup.getDBusAddress().toLower().trimmed());
368 ui->comp_DBusSelector->set(dbus);
370 ui->rb_WindowFrameless->setChecked(setup.useFramelessWindow());
371 ui->rb_WindowNormal->setChecked(!setup.useFramelessWindow());
374 ui->rb_SwiftStandalone->setChecked(mode == CLauncherSetup::Standalone ?
true :
false);
375 ui->rb_SwiftDistributed->setChecked(mode == CLauncherSetup::Distributed ?
true :
false);
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));
383 void CSwiftLauncher::saveSetup()
386 const QString dBus(ui->comp_DBusSelector->getDBusAddress());
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());
397 if (ui->rb_SwiftDistributed->isChecked()) { setup.
setCoreMode(CLauncherSetup::Distributed); }
403 bool CSwiftLauncher::warnAboutOtherSwiftApplications()
407 if (running.
isEmpty()) {
return true; }
410 const QString msg = u
"While using the wizard no other application should run.\nClose applications and try "
411 u
"again.\nCurrently running: " %
419 if (exeArgs.
isEmpty()) {
return exe; }
421 const QString cmd(exe +
" " + exeArgsString);
425 void CSwiftLauncher::startButtonPressed()
432 if (
sender == ui->tb_SwiftGui)
434 if (this->setSwiftGuiExecutable())
436 if (shift) { this->popupExecutableArgs(); }
440 else if (
sender == ui->tb_SwiftMappingTool)
442 ui->tb_SwiftMappingTool->setEnabled(
false);
443 m_startMappingToolWaitCycles = 2;
444 if (this->setSwiftDataExecutable())
446 if (shift) { this->popupExecutableArgs(); }
450 else if (
sender == ui->tb_SwiftCore)
452 if (this->isStandaloneGuiSelected()) { ui->rb_SwiftDistributed->setChecked(
true); }
453 ui->tb_SwiftCore->setEnabled(
false);
454 m_startCoreWaitCycles = 2;
455 if (this->setSwiftCoreExecutable())
457 if (shift) { this->popupExecutableArgs(); }
461 else if (sender == ui->tb_Database)
468 void CSwiftLauncher::dbusServerModeSelected(
bool selected)
470 if (!selected) {
return; }
471 if (!this->isStandaloneGuiSelected()) {
return; }
472 ui->rb_SwiftDistributed->setChecked(
true);
477 using namespace std::chrono_literals;
478 ui->fr_SwiftLauncherMain->showOverlayMessage(msg, 5s);
481 void CSwiftLauncher::showStatusMessage(
const QString &htmlMsg)
483 using namespace std::chrono_literals;
484 ui->fr_SwiftLauncherMain->showOverlayMessage(htmlMsg, 5s);
487 void CSwiftLauncher::showMainPage() { ui->sw_SwiftLauncher->setCurrentWidget(ui->pg_SwiftLauncherMain); }
489 void CSwiftLauncher::tabChanged(
int current)
491 if (current ==
static_cast<int>(PageUpdates)) { ui->comp_DataUpdates->display(); }
494 void CSwiftLauncher::showLogPage() { ui->sw_SwiftLauncher->setCurrentWidget(ui->pg_SwiftLauncherLog); }
496 void CSwiftLauncher::checkRunningApplicationsAndCore()
499 if (m_startCoreWaitCycles > 0) { m_startCoreWaitCycles--; }
500 if (m_startMappingToolWaitCycles > 0) { m_startMappingToolWaitCycles--; }
501 if (m_startGuiWaitCycles > 0) { m_startGuiWaitCycles--; }
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();
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);
514 void CSwiftLauncher::startWizard()
516 const bool show = this->warnAboutOtherSwiftApplications();
517 if (!
show) {
return; }
520 CGuiUtility::centerWidget(m_wizard.
data(),
this);
523 void CSwiftLauncher::onStyleSheetsChanged() { this->initStyleSheet(); }
525 void CSwiftLauncher::onDBusEditingFinished() { ui->rb_SwiftDistributed->setChecked(
true); }
527 void CSwiftLauncher::onCoreModeReleased()
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);
539 void CSwiftLauncher::showSimulatorConfigDirs()
548 if (s == ui->pb_P3DConfigDirs)
550 simDir = CFsDirectories::p3dDir();
551 simObjDir = CFsDirectories::p3dSimObjectsDir();
552 const QString versionHint = CFsDirectories::guessP3DVersion(simDir);
553 dirs = CFsDirectories::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(simObjDir, versionHint);
555 else if (s == ui->pb_FSXConfigDirs)
557 dirs = CFsDirectories::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths();
558 simDir = CFsDirectories::fsxDir();
559 simObjDir = CFsDirectories::fsxSimObjectsDir();
562 const QString info = u
"Sim.dir: " % simDir %
"\n" % u
"Sim.objects: " % simObjDir %
"\n" %
565 m_textEditDialog->setReadOnly();
566 m_textEditDialog->textEdit()->setText(info);
567 m_textEditDialog->show();
572 void CSwiftLauncher::requestMacMicrophoneAccess()
578 if (status == CMacOSMicrophoneAccess::Authorized) {
return; }
579 m_micAccess.requestAccess();
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
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.
void setAudioMode(AudioMode mode)
Audio mode.
void setCoreMode(CoreMode mode)
Core mode.
void setFramelessWindow(bool frameless)
Frameless window?
void setDBusAddress(const QString &dBusAddress)
DBus address.
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.
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.
Base class with a member CIdentifier to be inherited by a class which has an identity in the environm...
Class for emitting a log message.
Value class for matching log messages based on their categories.
AuthorizationStatus
Authorization status.
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
bool isEmpty() const
Synonym for empty.
Streamable status message, e.g.
Artifacts ("our software" products)
const CPlatform & getPlatform() const
OS.
bool isNewerThanCurrentBuild() const
Newer than the current build.
CDistribution getMostStableDistribution() const
Most stable distribution if any.
const QString & getChannel() const
Version channel (Alpha, Beta, Stable ..)
const QString & getVersion() const
Version info.
Value object encapsulating information of a location, kind of simplified CValueObject compliant versi...
void setFilter(const U &filter)
Set filter to choose list elements.
virtual void initialize(IDataLink *dataLink)
Subscribe using the given transport mechanism.
Simple hardcoded info about the corresponding simulator.
Basically a QObject free (delegate based) version of CCentralMultiSimulatorModelSetCachesProvider.
int getCachedModelsCount(const CSimulatorInfo &simulator) const
Look like IMultiSimulatorModelCaches interface.
void synchronizeCache(const CSimulatorInfo &simulator)
Look like IMultiSimulatorModelCaches interface.
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.
High level reusable GUI components.
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 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)
bool isEmpty() const const
QString join(QChar separator) const const
typedef KeyboardModifiers
void setInterval(int msec)
CoreMode
Core runs how and where?