mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-05-06 02:16:04 +08:00
Use overlay messages for validation
This commit is contained in:
@@ -75,6 +75,9 @@ namespace BlackGui
|
|||||||
|
|
||||||
// overlay
|
// overlay
|
||||||
this->setOverlaySizeFactors(0.8, 0.9);
|
this->setOverlaySizeFactors(0.8, 0.9);
|
||||||
|
this->setReducedInfo(true);
|
||||||
|
this->setForceSmall(true);
|
||||||
|
this->showKillButton(false);
|
||||||
|
|
||||||
// validators
|
// validators
|
||||||
CUpperCaseValidator *ucv = new CUpperCaseValidator(this);
|
CUpperCaseValidator *ucv = new CUpperCaseValidator(this);
|
||||||
@@ -433,7 +436,7 @@ namespace BlackGui
|
|||||||
m = CStatusMessage(this).validationError("No errors, but not connected, cannot send flight plan");
|
m = CStatusMessage(this).validationError("No errors, but not connected, cannot send flight plan");
|
||||||
}
|
}
|
||||||
ui->le_LastSent->setText(lastSent);
|
ui->le_LastSent->setText(lastSent);
|
||||||
this->showOverlayMessage(m, showOverlayMs);
|
this->showOverlayMessage(m, OverlayMessageMs);
|
||||||
m_sentFlightPlan = flightPlan; // last valid FP
|
m_sentFlightPlan = flightPlan; // last valid FP
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -782,7 +785,7 @@ namespace BlackGui
|
|||||||
}
|
}
|
||||||
|
|
||||||
// messages
|
// messages
|
||||||
this->showOverlayMessages(msgs, false, showOverlayMs);
|
this->showOverlayMessages(msgs, false, OverlayMessageMs);
|
||||||
|
|
||||||
// copy over
|
// copy over
|
||||||
if (msgs.isSuccess())
|
if (msgs.isSuccess())
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ namespace BlackGui
|
|||||||
BlackMisc::CDataReadOnly<BlackMisc::Simulation::Data::TLastModel> m_lastAircraftModel { this }; //!< recently used aircraft model
|
BlackMisc::CDataReadOnly<BlackMisc::Simulation::Data::TLastModel> m_lastAircraftModel { this }; //!< recently used aircraft model
|
||||||
BlackMisc::CDataReadOnly<BlackMisc::Network::Data::TLastServer> m_lastServer { this }; //!< recently used server (VATSIM, other)
|
BlackMisc::CDataReadOnly<BlackMisc::Network::Data::TLastServer> m_lastServer { this }; //!< recently used server (VATSIM, other)
|
||||||
|
|
||||||
static constexpr int showOverlayMs = 5000;
|
static constexpr int OverlayMessageMs = 5000;
|
||||||
|
|
||||||
//! Validate, generates status messages
|
//! Validate, generates status messages
|
||||||
BlackMisc::CStatusMessageList validateAndInitializeFlightPlan(BlackMisc::Aviation::CFlightPlan &fligtPlan);
|
BlackMisc::CStatusMessageList validateAndInitializeFlightPlan(BlackMisc::Aviation::CFlightPlan &fligtPlan);
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ namespace BlackGui
|
|||||||
}
|
}
|
||||||
|
|
||||||
CLoginComponent::CLoginComponent(QWidget *parent) :
|
CLoginComponent::CLoginComponent(QWidget *parent) :
|
||||||
QFrame(parent),
|
COverlayMessagesFrame(parent),
|
||||||
ui(new Ui::CLoginComponent)
|
ui(new Ui::CLoginComponent)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
@@ -102,6 +102,12 @@ namespace BlackGui
|
|||||||
ui->lblp_AircraftIcao->setToolTips("ok", "wrong");
|
ui->lblp_AircraftIcao->setToolTips("ok", "wrong");
|
||||||
ui->lblp_Callsign->setToolTips("ok", "wrong");
|
ui->lblp_Callsign->setToolTips("ok", "wrong");
|
||||||
|
|
||||||
|
// overlay
|
||||||
|
this->setOverlaySizeFactors(0.8, 0.5);
|
||||||
|
this->setReducedInfo(true);
|
||||||
|
this->setForceSmall(true);
|
||||||
|
this->showKillButton(false);
|
||||||
|
|
||||||
// Stored data
|
// Stored data
|
||||||
this->loadRememberedUserData();
|
this->loadRememberedUserData();
|
||||||
|
|
||||||
@@ -141,7 +147,7 @@ namespace BlackGui
|
|||||||
CServerList otherServers(m_otherTrafficNetworkServers.getThreadLocal());
|
CServerList otherServers(m_otherTrafficNetworkServers.getThreadLocal());
|
||||||
|
|
||||||
// add a testserver when no servers can be loaded
|
// add a testserver when no servers can be loaded
|
||||||
if (otherServers.isEmpty() && sGui->isRunningInDeveloperEnvironment())
|
if (otherServers.isEmpty() && (sGui->isRunningInDeveloperEnvironment() || CBuildConfig::isLocalDeveloperDebugBuild()))
|
||||||
{
|
{
|
||||||
otherServers.push_back(sGui->getGlobalSetup().getFsdTestServersPlusHardcodedServers());
|
otherServers.push_back(sGui->getGlobalSetup().getFsdTestServersPlusHardcodedServers());
|
||||||
CLogMessage(this).info("Added servers for testing");
|
CLogMessage(this).info("Added servers for testing");
|
||||||
@@ -151,7 +157,6 @@ namespace BlackGui
|
|||||||
connect(ui->pb_copyCredentialsVatsim, &QPushButton::clicked, this, &CLoginComponent::copyCredentialsToPilot);
|
connect(ui->pb_copyCredentialsVatsim, &QPushButton::clicked, this, &CLoginComponent::copyCredentialsToPilot);
|
||||||
connect(ui->pb_CopyCredentialsOtherServers, &QPushButton::clicked, this, &CLoginComponent::copyCredentialsToPilot);
|
connect(ui->pb_CopyCredentialsOtherServers, &QPushButton::clicked, this, &CLoginComponent::copyCredentialsToPilot);
|
||||||
this->setUiLoginState(false);
|
this->setUiLoginState(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CLoginComponent::~CLoginComponent()
|
CLoginComponent::~CLoginComponent()
|
||||||
@@ -202,7 +207,7 @@ namespace BlackGui
|
|||||||
{
|
{
|
||||||
if (ui->tw_Network->currentWidget() == ui->pg_FsdDetails)
|
if (ui->tw_Network->currentWidget() == ui->pg_FsdDetails)
|
||||||
{
|
{
|
||||||
CLogMessage(this).validationError("No login possible from this very tab, use VATSIM or other servers");
|
this->showOverlayMessage(CStatusMessage(this).validationError("No login possible from this very tab, use VATSIM or other servers"), OverlayMessageMs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const bool isConnected = sGui && sGui->getIContextNetwork()->isConnected();
|
const bool isConnected = sGui && sGui->getIContextNetwork()->isConnected();
|
||||||
@@ -218,14 +223,14 @@ namespace BlackGui
|
|||||||
{
|
{
|
||||||
if (!this->validateAircraftValues())
|
if (!this->validateAircraftValues())
|
||||||
{
|
{
|
||||||
CLogMessage(this).validationWarning("Invalid aircraft data, login not possible");
|
this->showOverlayMessage(CStatusMessage(this).validationWarning("Invalid aircraft data, login not possible"), OverlayMessageMs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CStatusMessageList pilotMsgs = ui->editor_Pilot->validate();
|
const CStatusMessageList pilotMsgs = ui->editor_Pilot->validate();
|
||||||
if (pilotMsgs.isFailure())
|
if (pilotMsgs.isFailure())
|
||||||
{
|
{
|
||||||
CLogMessage(this).validationWarning("Invalid pilot data, login not possible");
|
this->showOverlayMessage(CStatusMessage(this).validationWarning("Invalid pilot data, login not possible"), OverlayMessageMs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,9 @@
|
|||||||
|
|
||||||
#include "blackcore/vatsim/vatsimsettings.h"
|
#include "blackcore/vatsim/vatsimsettings.h"
|
||||||
#include "blackcore/data/vatsimsetup.h"
|
#include "blackcore/data/vatsimsetup.h"
|
||||||
#include "blackgui/blackguiexport.h"
|
|
||||||
#include "blackgui/settings/guisettings.h"
|
#include "blackgui/settings/guisettings.h"
|
||||||
|
#include "blackgui/blackguiexport.h"
|
||||||
|
#include "blackgui/overlaymessagesframe.h"
|
||||||
#include "blackmisc/simulation/data/lastmodel.h"
|
#include "blackmisc/simulation/data/lastmodel.h"
|
||||||
#include "blackmisc/simulation/simulatedaircraft.h"
|
#include "blackmisc/simulation/simulatedaircraft.h"
|
||||||
#include "blackmisc/aviation/callsign.h"
|
#include "blackmisc/aviation/callsign.h"
|
||||||
@@ -54,7 +55,7 @@ namespace BlackGui
|
|||||||
/*!
|
/*!
|
||||||
* Login component to flight network
|
* Login component to flight network
|
||||||
*/
|
*/
|
||||||
class BLACKGUI_EXPORT CLoginComponent : public QFrame
|
class BLACKGUI_EXPORT CLoginComponent : public COverlayMessagesFrame
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@@ -200,6 +201,7 @@ namespace BlackGui
|
|||||||
//! Tab widget (server) changed
|
//! Tab widget (server) changed
|
||||||
void onServerTabWidgetChanged(int index);
|
void onServerTabWidgetChanged(int index);
|
||||||
|
|
||||||
|
static const int OverlayMessageMs = 5000;
|
||||||
QScopedPointer<Ui::CLoginComponent> ui;
|
QScopedPointer<Ui::CLoginComponent> ui;
|
||||||
QScopedPointer<CDbQuickMappingWizard> m_mappingWizard;
|
QScopedPointer<CDbQuickMappingWizard> m_mappingWizard;
|
||||||
BlackMisc::CDigestSignal m_changedLoginDataDigestSignal { this, &CLoginComponent::loginDataChangedDigest, 1500, 10 };
|
BlackMisc::CDigestSignal m_changedLoginDataDigestSignal { this, &CLoginComponent::loginDataChangedDigest, 1500, 10 };
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ namespace BlackGui
|
|||||||
Q_ASSERT_X(sGui->getIContextNetwork(), Q_FUNC_INFO, "need network context");
|
Q_ASSERT_X(sGui->getIContextNetwork(), Q_FUNC_INFO, "need network context");
|
||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
ui->tw_ListViews->setCurrentIndex(0);
|
||||||
|
|
||||||
ui->tvp_AircraftModels->setAircraftModelMode(CAircraftModelListModel::OwnAircraftModelClient);
|
ui->tvp_AircraftModels->setAircraftModelMode(CAircraftModelListModel::OwnAircraftModelClient);
|
||||||
ui->tvp_AircraftModels->setResizeMode(CAircraftModelView::ResizingOff);
|
ui->tvp_AircraftModels->setResizeMode(CAircraftModelView::ResizingOff);
|
||||||
ui->tvp_AircraftModels->addFilterDialog();
|
ui->tvp_AircraftModels->addFilterDialog();
|
||||||
@@ -94,6 +96,10 @@ namespace BlackGui
|
|||||||
|
|
||||||
m_currentMappingsViewDelegate = new CCheckBoxDelegate(":/diagona/icons/diagona/icons/tick.png", ":/diagona/icons/diagona/icons/cross.png", this);
|
m_currentMappingsViewDelegate = new CCheckBoxDelegate(":/diagona/icons/diagona/icons/tick.png", ":/diagona/icons/diagona/icons/cross.png", this);
|
||||||
ui->tvp_RenderedAircraft->setItemDelegateForColumn(0, m_currentMappingsViewDelegate);
|
ui->tvp_RenderedAircraft->setItemDelegateForColumn(0, m_currentMappingsViewDelegate);
|
||||||
|
|
||||||
|
// overlay
|
||||||
|
this->setReducedInfo(true);
|
||||||
|
this->setForceSmall(true);
|
||||||
this->showKillButton(false);
|
this->showKillButton(false);
|
||||||
|
|
||||||
// Aircraft previews
|
// Aircraft previews
|
||||||
@@ -129,6 +135,12 @@ namespace BlackGui
|
|||||||
CMappingComponent::~CMappingComponent()
|
CMappingComponent::~CMappingComponent()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
const CLogCategoryList &CMappingComponent::getLogCategories()
|
||||||
|
{
|
||||||
|
static const CLogCategoryList cats({ CLogCategory::mapping(), CLogCategory::guiComponent() });
|
||||||
|
return cats;
|
||||||
|
}
|
||||||
|
|
||||||
int CMappingComponent::countCurrentMappings() const
|
int CMappingComponent::countCurrentMappings() const
|
||||||
{
|
{
|
||||||
Q_ASSERT(ui->tvp_RenderedAircraft);
|
Q_ASSERT(ui->tvp_RenderedAircraft);
|
||||||
@@ -182,7 +194,7 @@ namespace BlackGui
|
|||||||
if (!saFromBackend.hasValidCallsign()) { return; } // obviously deleted
|
if (!saFromBackend.hasValidCallsign()) { return; } // obviously deleted
|
||||||
const bool nowEnabled = sa.isEnabled();
|
const bool nowEnabled = sa.isEnabled();
|
||||||
if (saFromBackend.isEnabled() == nowEnabled) { return; } // already same value
|
if (saFromBackend.isEnabled() == nowEnabled) { return; } // already same value
|
||||||
CLogMessage(this).info("Request to %1 aircraft %2") << (nowEnabled ? "enable" : "disable") << saFromBackend.getCallsign().toQString();
|
CLogMessage(this).info("Request to %1 aircraft '%2'") << (nowEnabled ? "enable" : "disable") << saFromBackend.getCallsign().toQString();
|
||||||
sGui->getIContextNetwork()->updateAircraftEnabled(saFromBackend.getCallsign(), nowEnabled);
|
sGui->getIContextNetwork()->updateAircraftEnabled(saFromBackend.getCallsign(), nowEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,12 +230,12 @@ namespace BlackGui
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CCallsign CMappingComponent::validateRenderedCallsign() const
|
CCallsign CMappingComponent::validateRenderedCallsign()
|
||||||
{
|
{
|
||||||
const QString cs = ui->le_Callsign->text().trimmed();
|
const QString cs = ui->le_Callsign->text().trimmed();
|
||||||
if (!CCallsign::isValidAircraftCallsign(cs))
|
if (!CCallsign::isValidAircraftCallsign(cs))
|
||||||
{
|
{
|
||||||
CLogMessage(this).validationError("Invalid callsign for mapping");
|
this->showOverlayMessage(CStatusMessage(this).validationError("Invalid callsign for mapping"), OverlayMessageMs);
|
||||||
return CCallsign();
|
return CCallsign();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,7 +243,8 @@ namespace BlackGui
|
|||||||
const bool hasCallsign = ui->tvp_RenderedAircraft->container().containsCallsign(callsign);
|
const bool hasCallsign = ui->tvp_RenderedAircraft->container().containsCallsign(callsign);
|
||||||
if (!hasCallsign)
|
if (!hasCallsign)
|
||||||
{
|
{
|
||||||
CLogMessage(this).validationError("Unmapped callsign %1 for mapping") << callsign.asString();
|
const CStatusMessage msg = CStatusMessage(this).validationError("Unmapped callsign '%1' for mapping") << callsign.asString();
|
||||||
|
this->showOverlayMessage(msg);
|
||||||
return CCallsign();
|
return CCallsign();
|
||||||
}
|
}
|
||||||
return callsign;
|
return callsign;
|
||||||
@@ -245,14 +258,14 @@ namespace BlackGui
|
|||||||
const QString modelString = ui->completer_ModelStrings->getModelString();
|
const QString modelString = ui->completer_ModelStrings->getModelString();
|
||||||
if (modelString.isEmpty())
|
if (modelString.isEmpty())
|
||||||
{
|
{
|
||||||
CLogMessage(this).validationError("Missing model for mapping");
|
this->showOverlayMessage(CStatusMessage(this).validationError("Missing model for mapping"), OverlayMessageMs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool hasModel = ui->tvp_AircraftModels->container().containsModelString(modelString);
|
const bool hasModel = ui->tvp_AircraftModels->container().containsModelString(modelString);
|
||||||
if (!hasModel)
|
if (!hasModel)
|
||||||
{
|
{
|
||||||
CLogMessage(this).validationError("Invalid model for mapping, reload models");
|
this->showOverlayMessage(CStatusMessage(this).validationError("Invalid model for mapping, reloading model set"), OverlayMessageMs);
|
||||||
if (ui->tvp_AircraftModels->isEmpty())
|
if (ui->tvp_AircraftModels->isEmpty())
|
||||||
{
|
{
|
||||||
this->onModelsUpdateRequested();
|
this->onModelsUpdateRequested();
|
||||||
@@ -268,7 +281,8 @@ namespace BlackGui
|
|||||||
const CAircraftModelList models = sGui->getIContextSimulator()->getModelSetModelsStartingWith(modelString);
|
const CAircraftModelList models = sGui->getIContextSimulator()->getModelSetModelsStartingWith(modelString);
|
||||||
if (models.isEmpty())
|
if (models.isEmpty())
|
||||||
{
|
{
|
||||||
CLogMessage(this).validationError("No model for title: %1") << modelString;
|
const CStatusMessage msg = CStatusMessage(this).validationError("No model for title: '%1'") << modelString;
|
||||||
|
this->showOverlayMessage(msg, OverlayMessageMs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,11 +295,12 @@ namespace BlackGui
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CLogMessage(this).validationInfo("Ambigious title: %1, using %2") << modelString << model.getModelString();
|
const CStatusMessage msg = CStatusMessage(this).validationInfo("Ambigious title: '%1', using '%2'") << modelString << model.getModelString();
|
||||||
|
this->showOverlayMessage(msg, OverlayMessageMs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
model.setModelType(CAircraftModel::TypeManuallySet);
|
model.setModelType(CAircraftModel::TypeManuallySet);
|
||||||
CLogMessage(this).info("Requesting changes for %1") << callsign.asString();
|
CLogMessage(this).info("Requesting changes for '%1'") << callsign.asString();
|
||||||
changed = sGui->getIContextNetwork()->updateAircraftModel(aircraftFromBackend.getCallsign(), model, identifier());
|
changed = sGui->getIContextNetwork()->updateAircraftModel(aircraftFromBackend.getCallsign(), model, identifier());
|
||||||
}
|
}
|
||||||
if (aircraftFromBackend.isEnabled() != enabled)
|
if (aircraftFromBackend.isEnabled() != enabled)
|
||||||
@@ -295,7 +310,7 @@ namespace BlackGui
|
|||||||
|
|
||||||
if (!changed)
|
if (!changed)
|
||||||
{
|
{
|
||||||
CLogMessage(this).info("Model mapping, nothing to change");
|
this->showOverlayMessage(CLogMessage(this).info("Model mapping, nothing to change"), OverlayMessageMs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,14 +320,10 @@ namespace BlackGui
|
|||||||
const CCallsign callsign(this->validateRenderedCallsign());
|
const CCallsign callsign(this->validateRenderedCallsign());
|
||||||
if (callsign.isEmpty()) { return; }
|
if (callsign.isEmpty()) { return; }
|
||||||
const bool reset = sGui->getIContextSimulator()->resetToModelMatchingAircraft(callsign);
|
const bool reset = sGui->getIContextSimulator()->resetToModelMatchingAircraft(callsign);
|
||||||
if (reset)
|
const CStatusMessage msg = reset ?
|
||||||
{
|
CStatusMessage(this).info("Model reset for '%1'") << callsign.toQString() :
|
||||||
CLogMessage(this).info("Model reset for '%1'") << callsign.toQString();
|
CStatusMessage(this).info("Reset failed for '%1'") << callsign.toQString();
|
||||||
}
|
this->showOverlayMessage(msg);
|
||||||
else
|
|
||||||
{
|
|
||||||
CLogMessage(this).info("Reset failed for '%1'") << callsign.toQString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMappingComponent::onModelPreviewChanged(int state)
|
void CMappingComponent::onModelPreviewChanged(int state)
|
||||||
|
|||||||
@@ -61,6 +61,9 @@ namespace BlackGui
|
|||||||
//! Destructor
|
//! Destructor
|
||||||
virtual ~CMappingComponent();
|
virtual ~CMappingComponent();
|
||||||
|
|
||||||
|
//! Log categories
|
||||||
|
static const BlackMisc::CLogCategoryList &getLogCategories();
|
||||||
|
|
||||||
//! Number of current mappings
|
//! Number of current mappings
|
||||||
int countCurrentMappings() const;
|
int countCurrentMappings() const;
|
||||||
|
|
||||||
@@ -143,15 +146,16 @@ namespace BlackGui
|
|||||||
void updateRenderedAircraftView(bool forceUpdate = false);
|
void updateRenderedAircraftView(bool forceUpdate = false);
|
||||||
|
|
||||||
//! Check callsign entered
|
//! Check callsign entered
|
||||||
BlackMisc::Aviation::CCallsign validateRenderedCallsign() const;
|
BlackMisc::Aviation::CCallsign validateRenderedCallsign();
|
||||||
|
|
||||||
|
static constexpr int OverlayMessageMs = 5000;
|
||||||
QScopedPointer<Ui::CMappingComponent> ui;
|
QScopedPointer<Ui::CMappingComponent> ui;
|
||||||
BlackMisc::CSettingReadOnly<BlackGui::Settings::TViewUpdateSettings> m_settings { this, &CMappingComponent::settingsChanged }; //!< settings changed
|
|
||||||
bool m_missedRenderedAircraftUpdate = true; //! Rendered aircraft need update
|
bool m_missedRenderedAircraftUpdate = true; //! Rendered aircraft need update
|
||||||
QTimer m_updateTimer { this };
|
QTimer m_updateTimer { this };
|
||||||
BlackMisc::CTokenBucket m_bucket { 3, BlackMisc::PhysicalQuantities::CTime(5.0, BlackMisc::PhysicalQuantities::CTimeUnit::s()), 1};
|
BlackMisc::CTokenBucket m_bucket { 3, BlackMisc::PhysicalQuantities::CTime(5.0, BlackMisc::PhysicalQuantities::CTimeUnit::s()), 1};
|
||||||
Views::CCheckBoxDelegate *m_currentMappingsViewDelegate = nullptr; //! checkbox in view
|
Views::CCheckBoxDelegate *m_currentMappingsViewDelegate = nullptr; //! checkbox in view
|
||||||
BlackMisc::CIdentifier m_identifier { "MappingComponent", this };
|
BlackMisc::CIdentifier m_identifier { "MappingComponent", this };
|
||||||
|
BlackMisc::CSettingReadOnly<BlackGui::Settings::TViewUpdateSettings> m_settings { this, &CMappingComponent::settingsChanged }; //!< settings changed
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
Reference in New Issue
Block a user