6 #include <QDialogButtonBox>
8 #include <QIntValidator>
10 #include <QMessageBox>
12 #include <QProgressBar>
13 #include <QPushButton>
14 #include <QStringBuilder>
17 #include <QToolButton>
20 #include "ui_logincomponent.h"
51 using namespace swift::config;
53 using namespace swift::misc::aviation;
54 using namespace swift::misc::audio;
55 using namespace swift::misc::network;
56 using namespace swift::misc::simulation;
59 using namespace swift::core::context;
66 static const QStringList cats { CLogCategories::guiComponent() };
73 m_logoffCountdownTimer.
setObjectName(
"CLoginComponent:m_logoffCountdownTimer");
91 this->loadRememberedUserData();
115 ui->frp_CurrentServer->setReadOnly(
true);
116 ui->frp_CurrentServer->showPasswordField(
false);
117 ui->tb_Timeout->setIcon(m_iconPause);
121 ui->form_Pilot->validate();
128 this->updateUiConnectState();
132 if (!myself) {
return; }
142 if (currentWidget !=
this && currentWidget != this->
parentWidget())
148 ui->comp_OwnAircraft->setOwnModelAndIcaoValues();
150 this->updateUiConnectState();
151 this->blinkConnectButton();
157 ui->pb_LogoffTimeout->setMaximum(timeout.count());
158 ui->pb_LogoffTimeout->setValue(timeout.count());
159 m_logoffIntervalSeconds = timeout;
162 void CLoginComponent::loginCancelled()
164 m_logoffCountdownTimer.
stop();
165 ui->fr_TimeoutConnected->hide();
177 const bool vatsimLogin = this->isVatsimNetworkTabSelected();
179 ui->form_Pilot->setVatsimValidation(vatsimLogin);
180 this->updateUiConnectState();
188 if (!m_networkConnected)
194 CStatusMessage(
this).validationWarning(u
"Invalid aircraft data, login not possible"),
203 CStatusMessage(
this).validationWarning(u
"Invalid pilot data, login not possible"),
210 this->updateOwnAircraftCallsignAndPilotFromGuiValues();
211 ui->comp_OwnAircraft->updateOwnAircaftIcaoValuesFromGuiValues();
214 const CLoginMode mode = ui->comp_NetworkDetails->getLoginMode();
218 currentServer = this->getCurrentServer();
219 const CUser user = this->getUserFromPilotGuiValues();
222 ui->frp_CurrentServer->setServer(currentServer);
230 if (ui->comp_NetworkDetails->hasPartnerCallsign())
232 partnerCs = ui->comp_NetworkDetails->getPartnerCallsign();
246 "Callsign and the pilot/copilot callsign appear not to be synchronized", OverlayMessageMs);
257 Q_ASSERT_X(currentServer.
isValidForLogin(), Q_FUNC_INFO,
"invalid server");
260 CCrashHandler::instance()->crashAndLogInfoFlightNetwork(currentServer.
getEcosystem().
toQString(
true));
261 CCrashHandler::instance()->crashAndLogAppendInfo(currentServer.
getServerSessionId(
false));
265 m_lastAircraftModel.
set(ownModel);
281 CLogMessage::preformatted(msg);
284 this->setGuiLoginAsValues(ownAircraft);
290 void CLoginComponent::loadRememberedUserData()
294 ui->form_Pilot->setUser(lastUser);
295 ui->comp_OwnAircraft->setUser(lastUser);
298 void CLoginComponent::onSelectedServerChanged(
const CServer &server)
300 if (!m_updatePilotOnServerChanges) {
return; }
301 const bool vatsim = this->isVatsimNetworkTabSelected();
305 if ((vatsim && server.
getServerType() != CServer::FSDServer) ||
307 ui->form_Pilot->setUser(user);
310 void CLoginComponent::onSimulatorStatusChanged(
int status)
312 auto s =
static_cast<ISimulator::SimulatorStatus
>(status);
313 if (!this->hasValidContexts()) {
return; }
314 m_simulatorConnected = s.testFlag(ISimulator::Connected);
315 this->updateUiConnectState();
318 if (!m_simulatorConnected)
321 this->autoLogoffDetection();
329 if (to != CConnectionStatus::Connected) {
return; }
331 m_networkConnected =
true;
332 this->updateUiConnectState();
336 void CLoginComponent::onServerTabWidgetChanged(
int index)
339 if (!m_updatePilotOnServerChanges) {
return; }
340 const bool vatsim = this->isVatsimNetworkTabSelected();
341 const CServer server = vatsim ? this->getCurrentVatsimServer() : this->getCurrentOtherServer();
342 ui->form_Pilot->setUser(server.
getUser());
345 bool CLoginComponent::hasValidContexts()
const
355 CUser CLoginComponent::getUserFromPilotGuiValues()
const
357 CUser user = ui->form_Pilot->getUser();
358 user.
setCallsign(ui->comp_OwnAircraft->getCallsignFromGui());
362 CServer CLoginComponent::getCurrentVatsimServer()
const
364 CServer server = ui->comp_NetworkDetails->getCurrentVatsimServer();
374 CServer CLoginComponent::getCurrentOtherServer()
const {
return ui->comp_NetworkDetails->getCurrentOtherServer(); }
376 CServer CLoginComponent::getCurrentServer()
const
378 return this->isVatsimNetworkTabSelected() ? this->getCurrentVatsimServer() : this->getCurrentOtherServer();
381 void CLoginComponent::startLogoffTimerCountdown()
383 ui->pb_LogoffTimeout->setValue(m_logoffIntervalSeconds.count());
385 m_logoffCountdownTimer.
start();
386 ui->fr_TimeoutConnected->show();
397 ui->le_LoginAsAircaft->setText(ac);
398 ui->le_LoginAsAircaft->home(
false);
399 ui->le_LoginCallsign->setText(cs);
402 void CLoginComponent::logoffCountdown()
404 int v = ui->pb_LogoffTimeout->value();
407 ui->pb_LogoffTimeout->setValue(v);
410 m_logoffCountdownTimer.
stop();
415 void CLoginComponent::autoLogoffDetection()
417 using namespace std::chrono_literals;
418 if (!this->hasValidContexts()) {
return; }
423 u
"Auto logoff in progress (could be simulator shutdown, crash, closing simulator)");
424 const auto delay = 20s;
427 this->startLogoffTimerCountdown();
432 void CLoginComponent::autoLogoffFrameRate(
bool fatal)
434 using namespace std::chrono_literals;
436 if (!this->hasValidContexts()) {
return; }
439 const auto msg = fatal ?
CStatusMessage(
this, CStatusMessage::SeverityError,
440 u
"Sim frame rate too low to maintain constant simulation rate. "
441 u
"Disconnecting to avoid disrupting the network.") :
443 u
"Sim frame rate too low to maintain constant simulation rate. Reduce "
444 u
"graphics quality to avoid disconnection.");
445 const auto delay = 20s;
450 this->startLogoffTimerCountdown();
456 void CLoginComponent::onSimulatorModelChanged(
const CAircraftModel &model)
460 if (isNetworkConnected) {
return; }
467 if (!reverseModel.isLoadedFromDb()) { reverseModel = model; }
470 const QString modelStr(reverseModel.hasModelString() ? reverseModel.getModelString() :
"<unknown>");
471 if (!reverseModel.hasModelString())
474 << modelStr << reverseModel.toQString();
478 ui->comp_OwnAircraft->setOwnModelAndIcaoValues(reverseModel);
481 this->updateOwnAircraftCallsignAndPilotFromGuiValues();
487 void CLoginComponent::toggleTimeout()
489 if (m_logoffCountdownTimer.
isActive())
491 m_logoffCountdownTimer.
stop();
492 ui->tb_Timeout->setIcon(m_iconPlay);
496 m_logoffCountdownTimer.
start();
497 ui->tb_Timeout->setIcon(m_iconPause);
501 void CLoginComponent::updateUiConnectState()
503 ui->fr_LoginDisconnected->setVisible(!m_networkConnected);
504 ui->fr_LogoffConfirmationConnected->setVisible(m_networkConnected);
506 const QString s = m_networkConnected ? QStringLiteral(
"disconnect") : QStringLiteral(
"connect");
507 ui->pb_Ok->setText(s);
509 if (m_networkConnected) { ui->pb_Ok->setDisabled(
false); }
510 else { ui->pb_Ok->setDisabled(!m_simulatorConnected); }
513 void CLoginComponent::blinkConnectButton()
515 if (!ui->pb_Ok->isEnabled()) {
return; }
516 ui->pb_Ok->setProperty(
"blinkOn",
true);
517 static constexpr
int blinkLength = 100;
518 static constexpr
int blinkTimes = 10;
520 auto timer =
new QTimer(
this);
522 if (++*count <= blinkTimes) { ui->pb_Ok->setProperty(
"blinkOn", !ui->pb_Ok->property(
"blinkOn").toBool()); }
525 ui->pb_Ok->setProperty(
"blinkOn",
false);
527 timer->deleteLater();
529 ui->pb_Ok->style()->unpolish(ui->pb_Ok);
530 ui->pb_Ok->style()->polish(ui->pb_Ok);
532 timer->setObjectName(
"blinker");
533 timer->start(blinkLength);
536 bool CLoginComponent::isVatsimNetworkTabSelected()
const
538 return ui->comp_NetworkDetails->isVatsimServerSelected();
545 return IContextOwnAircraft::getDefaultOwnAircraftModel();
548 bool CLoginComponent::updateOwnAircraftCallsignAndPilotFromGuiValues()
550 if (!this->hasValidContexts()) {
return false; }
552 const CCallsign cs = ui->comp_OwnAircraft->getCallsignFromGui();
553 bool changedCallsign =
false;
558 changedCallsign =
true;
561 const CUser uiUser = ui->form_Pilot->getUser();
566 bool changedPilot =
false;
567 if (ownAircraft.
getPilot() != pilot)
572 return changedCallsign || changedPilot;
575 void CLoginComponent::updateGui()
577 if (!m_networkConnected) {
return; }
578 if (!this->hasValidContexts()) {
return; }
582 this->setGuiLoginAsValues(ownAircraft);
583 this->updateUiConnectState();
584 ui->comp_OwnAircraft->setOwnModelAndIcaoValues();
587 ui->frp_CurrentServer->setServer(server);
588 ui->comp_NetworkDetails->setLoginMode(nwc->
getLoginMode());
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
const context::IContextAudio * getIContextAudio() const
Direct access to contexts if a CCoreFacade has been initialized.
const context::IContextOwnAircraft * getIContextOwnAircraft() const
Direct access to contexts if a CCoreFacade has been initialized.
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.
bool supportsContexts(bool ignoreShutdownTest=false) const
Supports contexts.
CWebDataServices * getWebDataServices() const
Get the web data services.
swift::misc::simulation::CAircraftModel getModelForModelString(const QString &modelString) const
Model for model string if any.
virtual swift::misc::CStatusMessage disconnectFromNetwork()=0
Disconnect from network.
virtual swift::misc::CStatusMessage connectToNetwork(const swift::misc::network::CServer &server, const QString &extraLiveryString, bool sendLivery, const QString &extraModelString, bool sendModelString, const swift::misc::aviation::CCallsign &partnerCallsign, swift::misc::network::CLoginMode loginMode)=0
Connect to Network.
virtual swift::misc::network::CLoginMode getLoginMode() const =0
Login mode.
virtual swift::misc::network::CServer getConnectedServer() const =0
Server which is connected, if not connected empty default object.
virtual bool isConnected() const =0
Network connected?
virtual bool updateOwnAircraftPilot(const swift::misc::network::CUser &pilot)=0
Set current pilot.
virtual bool updateOwnCallsign(const swift::misc::aviation::CCallsign &callsign)=0
Set callsign.
virtual swift::misc::simulation::CSimulatedAircraft getOwnAircraft() const =0
Get own aircraft.
virtual ISimulator::SimulatorStatus getSimulatorStatus() const =0
Simulator combined status.
swift::misc::CStatusMessage setLastVatsimServer(const swift::misc::network::CServer &server)
Set value of last VATSIM server.
swift::misc::CStatusMessage setLastServer(const swift::misc::network::CServer &server)
Set value of last server.
swift::misc::network::CServer getLastVatsimServer() const
Last VATSIM server (VATSIM only)
swift::misc::network::CServer getLastServer() const
Last server (all networks)
QString setExtraWindowTitle(const QString &extraInfo, QWidget *mainWindowWidget=mainApplicationWidget()) const
Set window title.
void closeOverlay()
Close button clicked.
bool showOverlayHTMLMessage(const QString &htmlMessage, std::chrono::milliseconds timeout=std::chrono::milliseconds(0))
HTML message.
void setForceSmall(bool force)
Force small (smaller layout)
void setOverlaySizeFactors(double widthFactor, double heightFactor, double middleFactor=2)
Set the size factors.
void setReducedInfo(bool reduced)
Display reduced information.
Using this class provides a QFrame with the overlay functionality already integrated.
Login component to flight network.
void toggleNetworkConnection()
Login requested.
~CLoginComponent()
Destructor.
void loginOrLogoffCancelled()
Cancelled.
void mainInfoAreaChanged(const QWidget *currentWidget)
Main info area changed.
void setLogoffCountdown(std::chrono::seconds timeout=LogoffIntervalSeconds)
Set a logoff time.
void requestNetworkSettings()
Request network settings.
void loginOrLogoffSuccessful()
Login.
void requestLoginPage()
Request to be shown.
void requestNetworkSettings()
Request network settings.
void currentServerChanged(const misc::network::CServer &server)
Current selected server changed.
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.
void inputSignal()
Received input signal, or manually trigger.
Class for emitting a log message.
Derived & validationInfo(const char16_t(&format)[N])
Set the severity to info, providing a format string, and adding the validation category.
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
Streamable status message, e.g.
bool isSuccess() const
Operation considered successful.
void addCategories(const CLogCategoryList &categories)
Add categories, avoids duplicates.
Status messages, e.g. from Core -> GUI.
bool isFailure() const
Any message is marked as failure.
const QString & asString() const
Get code.
Value object encapsulating information of a callsign.
const QString & asString() const
Get callsign (normalized)
bool isEmpty() const
Is empty?
QString toQString(bool i18n=false) const
Cast as QString.
Value object encapsulating information about a connection status.
Value object encapsulating information about login mode.
bool isObserver() const
Is login as observer?
Value object encapsulating information of a server.
bool isValidForLogin() const
Is valid for login?
void setUser(const CUser &user)
Set user.
const CEcosystem & getEcosystem() const
Get the ecosystem.
const CUser & getUser() const
Get user.
ServerType getServerType() const
Get server type.
QString getServerSessionId(bool onlyConnected) const
Identifying a session, if not connected empty.
Value object encapsulating information of a user.
const aviation::CAirportIcaoCode & getHomeBase() const
Homebase.
const QString & getRealName() const
Get full name.
void setRealName(const QString &realname)
Set real name.
QString getRealNameAndId() const
Real name and id.
void setId(const QString &id)
Set id.
const QString & getId() const
Get id.
void setHomeBase(const aviation::CAirportIcaoCode &homebase)
Set homebase.
bool setCallsign(const aviation::CCallsign &callsign)
Set associated callsign.
bool hasValidVatsimId() const
Has a valid VATSIM id?
Aircraft model (used by another pilot, my models on disk)
const QString & getModelString() const
Model key, either queried or loaded from simulator model.
bool hasAircraftDesignator() const
Has aircraft designator?
Comprehensive information of an aircraft.
void setCallsign(const aviation::CCallsign &callsign)
Set callsign.
const QString & getAirlineIcaoCodeDesignator() const
Airline ICAO code designator.
bool hasAirlineDesignator() const
Valid airline designator.
bool hasModelString() const
Has model string?
const network::CUser & getPilot() const
Get user.
const aviation::CCallsign & getCallsign() const
Get callsign.
const QString & getAircraftIcaoCodeDesignator() const
Aircraft ICAO code designator.
const simulation::CAircraftModel & getModel() const
Get model (model used for mapping)
QString getCallsignAsString() const
Get callsign.
const QString & getModelString() const
Get model string.
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.
QDateTime currentDateTimeUtc()
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void setObjectName(QAnyStringView name)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
char * toString(QSizePolicy sp)
void setInterval(int msec)
bool isActive() const const
GUI aircraft values, formatted.
QString ownLiverySend
send livery
QString ownAircraftModelStringSend
send model string
bool useModelString
use model string