4 #include "ui_swiftguistd.h"
29 #if defined(Q_OS_MACOS)
36 #include <QMessageBox>
39 #include <QStackedWidget>
63 using namespace swift::core::context;
67 using namespace swift::misc::network;
68 using namespace swift::misc::aviation;
69 using namespace swift::misc::physical_quantities;
70 using namespace swift::misc::geo;
71 using namespace swift::misc::audio;
72 using namespace swift::misc::input;
73 using namespace swift::misc::simulation;
74 using namespace swift::config;
82 Q_ASSERT_X(
sGui, Q_FUNC_INFO,
"Need sGui");
107 void SwiftGuiStd::performGracefulShutdown()
109 if (!m_init) {
return; }
112 Q_ASSERT_X(CThreadUtils::thisIsMainThread(), Q_FUNC_INFO,
"Should shutdown in main thread");
115 this->stopAllTimers(
true);
118 if (m_contextNetworkAvailable)
122 if (m_contextAudioAvailable)
132 ui->comp_MainInfoArea->dockAllWidgets();
137 if (!
sGui || !myself) {
return; }
156 if (!myself) {
return; }
157 myself->loginRequested();
162 if (this->triggerAutoPublishDialog())
175 this->performGracefulShutdown();
223 this->setMainPageToInfoArea();
224 ui->comp_MainInfoArea->selectArea(infoArea);
227 void SwiftGuiStd::setSettingsPage(
int settingsTabIndex)
229 this->setMainPageInfoArea(CMainInfoAreaComponent::InfoAreaSettings);
230 if (settingsTabIndex < 0) {
return; }
231 ui->comp_MainInfoArea->getSettingsComponent()->setCurrentIndex(settingsTabIndex);
236 return ui->sw_MainMiddle->currentIndex() ==
static_cast<int>(mainPage);
239 void SwiftGuiStd::loginRequested()
243 const bool changed = MainPageLogin != ui->sw_MainMiddle->currentIndex();
244 this->setMainPage(MainPageLogin);
252 void SwiftGuiStd::onKickedFromNetwork(
const QString &kickMessage)
254 this->updateGuiStatusInformation();
256 const QString msgText = kickMessage.
isEmpty() ? QStringLiteral(
"You have been kicked from the network") :
257 QStringLiteral(
"You have been kicked: '%1'").arg(kickMessage);
265 this->updateGuiStatusInformation();
270 case CConnectionStatus::Connected: this->playNotifcationSound(CNotificationSounds::NotificationLogin);
break;
271 case CConnectionStatus::Disconnected: this->playNotifcationSound(CNotificationSounds::NotificationLogoff);
break;
276 void SwiftGuiStd::handleTimerBasedUpdates()
278 this->setContextAvailability();
279 this->updateGuiStatusInformation();
282 this->reloadOwnAircraft();
285 void SwiftGuiStd::setContextAvailability()
287 const bool corePreviouslyAvailable = m_coreAvailable;
294 else { m_coreAvailable =
false; }
295 if (isShuttingDown) {
return; }
296 if (m_coreAvailable && m_coreFailures > 0) { m_coreFailures--; }
297 else if (!m_coreAvailable && m_coreFailures < MaxCoreFailures) { m_coreFailures++; }
298 else if (!m_coreAvailable && !m_displayingDBusReconnect) { this->displayDBusReconnectDialog(); }
299 m_contextNetworkAvailable =
304 if (m_coreAvailable != corePreviouslyAvailable)
315 void SwiftGuiStd::updateGuiStatusInformation()
319 static const QString dBusTimestamp(
"%1 %2");
320 static const QString local(
"local");
323 ui->comp_InfoBarStatus->setDBusStatus(dBus && m_coreAvailable);
324 ui->comp_InfoBarStatus->setDBusTooltip(
329 static const QString unavailable(
"unavailable");
330 ui->comp_InfoBarStatus->setDBusStatus(
false);
331 ui->comp_InfoBarStatus->setDBusTooltip(unavailable);
335 void SwiftGuiStd::onChangedWindowOpacity(
int opacity)
337 qreal o = opacity / 100.0;
338 o = o < 0.3 ? 0.3 : o;
339 o = o > 1.0 ? 1.0 : o;
341 ui->comp_MainInfoArea->getSettingsComponent()->setGuiOpacity(o * 100.0);
344 void SwiftGuiStd::toggleWindowStayOnTop()
349 void SwiftGuiStd::toggleWindowVisibility()
359 void SwiftGuiStd::onStyleSheetsChanged() { this->initStyleSheet(); }
361 void SwiftGuiStd::onToggledWindowsOnTop(
bool onTop)
367 ui->comp_MainInfoArea->allFloatingOnTop();
371 void SwiftGuiStd::onCurrentMainWidgetChanged(
int currentIndex)
374 Q_UNUSED(currentIndex)
377 void SwiftGuiStd::onChangedMainInfoAreaFloating(
bool floating)
388 ui->fr_CentralFrameInside->showOverlayHTMLMessage(msg);
391 void SwiftGuiStd::focusInMainEntryField() { ui->comp_MainKeypadArea->focusInEntryField(); }
393 void SwiftGuiStd::focusInTextMessageEntryField()
395 if (!ui->comp_MainInfoArea->getTextMessageComponent()) {
return; }
396 if (ui->comp_MainInfoArea->getTextMessageComponent()->isParentDockWidgetFloating())
398 ui->comp_MainInfoArea->getTextMessageComponent()->activateWindow();
399 ui->comp_MainInfoArea->getTextMessageComponent()->focusTextEntry();
401 else { this->focusInMainEntryField(); }
408 void SwiftGuiStd::onNavigatorClosed()
414 void SwiftGuiStd::verifyPrerequisites()
425 #if defined(Q_OS_MACOS)
432 CLogMessage(
this).error(u
"Cannot access the keyboard. Is \"Input Monitoring\" for swift enabled?"));
446 using namespace std::chrono_literals;
452 if (invalid.
isEmpty()) {
return; }
455 u
"Model set validation has found %1 invalid models for '%2', check the model validation")
461 this->displayValidationDialog();
462 m_validationDialog->validatedModelSet(simulator, valid, invalid, stopped, msgs);
465 void SwiftGuiStd::displayValidationDialog()
469 m_validationDialog->show();
472 void SwiftGuiStd::checkDbDataLoaded()
476 Q_ASSERT_X(CThreadUtils::thisIsMainThread(), Q_FUNC_INFO,
"Wrong thread, needs to run in main thread");
477 const CEntityFlags::Entity loadEntities =
479 if (loadEntities == CEntityFlags::NoEntity)
481 m_dbDataLoading =
false;
486 m_dbLoadDialog->newerOrEmptyEntitiesDetected(loadEntities);
491 if (!m_contextAudioAvailable) {
return; }
492 if (!m_audioSettings.
get().isNotificationFlagSet(notification)) {
return; }
497 void SwiftGuiStd::displayLog() { ui->comp_MainInfoArea->displayLog(); }
499 void SwiftGuiStd::displayNetworkSettings()
502 this->setMainPageInfoArea(CMainInfoAreaComponent::InfoAreaSettings);
503 ui->comp_MainInfoArea->getSettingsComponent()->setTab(CSettingsComponent::SettingTabServers);
506 void SwiftGuiStd::onPttChanged(
bool enabled)
513 enabled ? CNotificationSounds::PTTClickKeyDown : CNotificationSounds::PTTClickKeyUp,
true);
516 void SwiftGuiStd::displayDBusReconnectDialog()
518 if (m_displayingDBusReconnect) {
return; }
522 m_displayingDBusReconnect =
true;
524 static const QString informativeText(
"Do you want to try to reconnect? 'Abort' will close the GUI.\n\nDBus: '%1'");
527 msgBox.setText(
"swift core not reachable!");
528 msgBox.setInformativeText(informativeText.arg(dBusAddress));
531 const int ret = msgBox.exec();
536 CGuiApplication::exit(EXIT_FAILURE);
540 m_displayingDBusReconnect =
false;
542 if (msg.
isSuccess()) { m_coreFailures = 0; }
544 CLogMessage::preformatted(msg);
547 void SwiftGuiStd::onShowOverlayVariant(
const CVariant &variant, std::chrono::milliseconds duration)
550 ui->fr_CentralFrameInside->showOverlayVariant(variant, duration);
556 ui->fr_CentralFrameInside->showOverlayInlineTextMessage(tab);
559 void SwiftGuiStd::onShowOverlayInlineTextMessageCallsign(
const CCallsign &callsign)
562 ui->fr_CentralFrameInside->showOverlayInlineTextMessage(callsign);
565 bool SwiftGuiStd::triggerAutoPublishDialog()
567 if (!CAutoPublishData::existAutoPublishFiles()) {
return false; }
569 constexpr qint64 deltaT = 48 * 60 * 60 * 1000;
570 const qint64 lastDialogTs = m_lastAutoPublish.
get();
572 if (!showAutoPublish) {
return false; }
576 QStringLiteral(
"Do you want to help improving swift by uploading anonymized data?"),
585 this->autoPublishDialog();
589 bool SwiftGuiStd::startModelBrowser()
592 m_modelBrower->exec();
596 bool SwiftGuiStd::startAFVMap()
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
virtual void mousePressEvent(QMouseEvent *event)
virtual void mouseMoveEvent(QMouseEvent *event)
void currentMainInfoAreaChanged(const QWidget *currentWidget)
Main info area has changed.
QAction * getToggleStayOnTopAction(QObject *parent)
Get a minimize action which minimizes the window.
SwiftGuiStd(WindowMode windowMode, QWidget *parent=nullptr)
Constructor.
virtual ~SwiftGuiStd()
Destructor.
QAction * getToggleWindowVisibilityAction(QObject *parent)
Get a minimize action which minimizes the window.
virtual void closeEvent(QCloseEvent *event)
MainPageIndex
Main page indexes.
QAction * getWindowNormalAction(QObject *parent)
Get a minimize action which minimizes the window.
QAction * getWindowMinimizeAction(QObject *parent)
Get a minimize action which minimizes the window.
virtual void changeEvent(QEvent *event)
virtual void mouseReleaseEvent(QMouseEvent *event)
const context::IContextAudio * getIContextAudio() const
Direct access to contexts if a CCoreFacade has been initialized.
data::CGlobalSetup getGlobalSetup() const
Global setup.
const context::IContextApplication * getIContextApplication() const
Direct access to contexts if a CCoreFacade has been initialized.
CCoreFacade * getCoreFacade()
Get the facade.
bool hasWebDataServices() const
Web data services available?
const context::IContextNetwork * getIContextNetwork() const
Direct access to contexts if a CCoreFacade has been initialized.
bool isShuttingDown() const
Is application shutting down?
const context::IContextSimulator * getIContextSimulator() const
Direct access to contexts if a CCoreFacade has been initialized.
const CCoreFacadeConfig & getCoreFacadeConfig() const
The core facade config.
const context::CContextAudioBase * getCContextAudioBase() const
Direct access to contexts if a CCoreFacade has been initialized.
bool supportsContexts(bool ignoreShutdownTest=false) const
Supports contexts.
CWebDataServices * getWebDataServices() const
Get the web data services.
bool requiresDBusConnection() const
Requires DBus connection (at least one remote)?
QString getDBusAddress() const
DBus address.
QString getDBusAddress() const
DBus address if any.
swift::misc::CStatusMessage tryToReconnectWithDBus()
In case connection between DBus parties is lost, try to reconnect.
swift::misc::network::CEntityFlags::Entity getSynchronizedEntitiesWithNewerSharedFileOrEmpty(bool syncData=true, swift::misc::network::CEntityFlags::Entity entities=swift::misc::network::CEntityFlags::AllDbEntities)
Synchronized entities either empty or with newer shared file.
void playNotification(swift::misc::audio::CNotificationSounds::NotificationFlag notification, bool considerSettings, int volume=-1)
Notification sounds.
virtual void unregisterApplication(const misc::CIdentifier &application)=0
Unregister application.
virtual void synchronizeLocalSettings()=0
Update local settings with settings from core.
virtual misc::CIdentifier registerApplication(const misc::CIdentifier &application)=0
Register application, can also be used for ping.
bool isEmptyObject() const
Empty object?
virtual swift::misc::CStatusMessage disconnectFromNetwork()=0
Disconnect from network.
virtual bool isConnected() const =0
Network connected?
virtual swift::misc::CStatusMessageList verifyPrerequisites() const =0
Verify prerequisites for simulation like an existing model set.
swift::misc::network::CUrl getAfvMapUrl() const
AFV map URL.
Main window which can be frameless.
bool handleMousePressEvent(QMouseEvent *event)
Mouse press, required for frameless window.
void showMinimizedModeChecked()
Check mode and then show minimized.
QPoint m_framelessDragPosition
position, if moving is handled with frameless window
void showNormalModeChecked()
Check mode and then show normal.
bool handleMouseMoveEvent(QMouseEvent *event)
Mouse moving, required for frameless window.
void setDynamicProperties(bool frameless)
Set dynamic properties such as frameless.
void registerMainApplicationWidget(QWidget *mainWidget)
Register main application window widget if this is known.
void processEventsToRefreshGui() const
Allow the GUI to refresh by processing events, call the event loop.
QDialog::DialogCode showCloseDialog(QMainWindow *mainWindow, QCloseEvent *closeEvent)
Show close dialog.
void gracefulShutdown()
Graceful shutdown.
bool toggleStayOnTop()
Toggle stay on top.
void openUrl(const swift::misc::network::CUrl &url)
Open a given URL.
Direct acccess to main window`s status bar, info bar and such.
virtual bool displayInOverlayWindow(const swift::misc::CStatusMessage &message, std::chrono::milliseconds timeout=std::chrono::milliseconds(0))
Display in overlay window.
Dialog for CAircraftModelValidationComponent.
Load data from DB as dialog.
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...
bool isMyIdentifier(const CIdentifier &otherIdentifier) const
My identifier?
const CIdentifier & identifier() const
Get identifier.
Class for emitting a log message.
bool isEmpty() const
Message empty.
Derived & validationWarning(const char16_t(&format)[N])
Set the severity to warning, providing a format string, and adding the validation category.
Derived & error(const char16_t(&format)[N])
Set the severity to error, providing a format string.
size_type size() const
Returns number of elements in the sequence.
void push_back(const T &value)
Appends an element at the end of the sequence.
reference front()
Access the first element.
bool isEmpty() const
Synonym for empty.
Streamable status message, e.g.
bool isSuccess() const
Operation considered successful.
bool clampSeverity(StatusSeverity severity)
Clip/reduce severity if higher (more critical)
Status messages, e.g. from Core -> GUI.
bool hasWarningOrErrorMessages() const
Warning or error messages.
Wrapper around QVariant which provides transparent access to CValueObject methods of the contained ob...
Value object encapsulating information of a callsign.
QString toQString(bool i18n=false) const
Cast as QString.
Value object encapsulating information about a connection status.
ConnectionStatus getConnectionStatus() const
Get status.
Value object encapsulating a list of aircraft models.
Simple hardcoded info about the corresponding simulator.
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
Backend services of the swift project, like dealing with the network or the simulators.
High level reusable GUI components.
Free functions in swift::misc.
void triggered(bool checked)
QDateTime currentDateTimeUtc()
qint64 currentMSecsSinceEpoch()
QString toString(QStringView format) 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)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
QObject * parent() const const
bool isEmpty() const const
NotificationFlag
Play notification.