Ref T225, use coordinate dialog in weather component

Remark: There was a redundant, also unfinished code in weather UI component for coordinate entry. This is now encapsulated in coordinate form/dialog.
This commit is contained in:
Klaus Basan
2018-01-18 14:42:55 +01:00
parent a764ea7534
commit 0916c90038
4 changed files with 89 additions and 149 deletions

View File

@@ -44,6 +44,9 @@ namespace BlackGui
ui(new Ui::CWeatherComponent) ui(new Ui::CWeatherComponent)
{ {
ui->setupUi(this); ui->setupUi(this);
m_coordinateDialog->showElevation(false);
m_coordinateDialog->setReadOnly(ui->cb_UseOwnAcftPosition->isChecked());
connect(ui->pb_Coordinate, &QPushButton::clicked, this, &CWeatherComponent::showCoordinateDialog);
m_weatherScenarios = CWeatherGrid::getAllScenarios(); m_weatherScenarios = CWeatherGrid::getAllScenarios();
for (const auto &scenario : as_const(m_weatherScenarios)) for (const auto &scenario : as_const(m_weatherScenarios))
@@ -56,18 +59,18 @@ namespace BlackGui
ui->pb_ActivateWeather->setIcon(CIcons::metar()); ui->pb_ActivateWeather->setIcon(CIcons::metar());
setupConnections(); setupConnections();
setupInputValidators(); ui->lbl_Status->setText({});
setupCompleter();
// hotkeys // hotkeys
const QString swift(CGuiActionBindHandler::pathSwiftPilotClient()); const QString swift(CGuiActionBindHandler::pathSwiftPilotClient());
m_hotkeyBindings.append(CGuiActionBindHandler::bindButton(ui->pb_ActivateWeather, swift + "Weather/Toggle weather", true)); m_hotkeyBindings.append(CGuiActionBindHandler::bindButton(ui->pb_ActivateWeather, swift + "Weather/Toggle weather", true));
m_hotkeyBindings.append(CGuiActionBindHandler::bindButton(ui->pb_ActivateWeather, swift + "Weather/Force CAVOK", true));
// Set interval to 5 min // Set interval to 5 min
m_weatherUpdateTimer.setInterval(1000 * 60 * 5); m_weatherUpdateTimer.setInterval(1000 * 60 * 5);
// Call this method deferred in order to have the component fully initialized, e.g. object name set by the parent // Call this method deferred in order to have the component fully initialized, e.g. object name set by the parent
QTimer::singleShot(0, this, &CWeatherComponent::updateWeatherInformation); QTimer::singleShot(1000, this, &CWeatherComponent::updateWeatherInformation);
} }
CWeatherComponent::~CWeatherComponent() CWeatherComponent::~CWeatherComponent()
@@ -76,13 +79,13 @@ namespace BlackGui
bool CWeatherComponent::setParentDockWidgetInfoArea(CDockWidgetInfoArea *parentDockableWidget) bool CWeatherComponent::setParentDockWidgetInfoArea(CDockWidgetInfoArea *parentDockableWidget)
{ {
CEnableForDockWidgetInfoArea::setParentDockWidgetInfoArea(parentDockableWidget); CEnableForDockWidgetInfoArea::setParentDockWidgetInfoArea(parentDockableWidget);
bool c = connect(this->getParentInfoArea(), &CInfoArea::changedInfoAreaTabBarIndex, this, &CWeatherComponent::ps_infoAreaTabBarChanged); bool c = connect(this->getParentInfoArea(), &CInfoArea::changedInfoAreaTabBarIndex, this, &CWeatherComponent::infoAreaTabBarChanged);
Q_ASSERT_X(c, Q_FUNC_INFO, "failed connect"); Q_ASSERT_X(c, Q_FUNC_INFO, "failed connect");
Q_ASSERT_X(parentDockableWidget, Q_FUNC_INFO, "missing parent"); Q_ASSERT_X(parentDockableWidget, Q_FUNC_INFO, "missing parent");
return c && parentDockableWidget; return c && parentDockableWidget;
} }
void CWeatherComponent::ps_infoAreaTabBarChanged(int index) void CWeatherComponent::infoAreaTabBarChanged(int index)
{ {
// ignore in those cases // ignore in those cases
if (!this->isVisibleWidget()) { return; } if (!this->isVisibleWidget()) { return; }
@@ -93,25 +96,19 @@ namespace BlackGui
Q_UNUSED(index); Q_UNUSED(index);
} }
void CWeatherComponent::toggleUseOwnAircraftPosition(bool checked) void CWeatherComponent::toggleUseOwnAircraftPosition(bool useOwnAircraftPosition)
{ {
m_lastOwnAircraftPosition = {}; m_lastOwnAircraftPosition = {};
if (checked) m_coordinateDialog->setReadOnly(useOwnAircraftPosition);
if (useOwnAircraftPosition)
{ {
ui->le_LatOrIcao->setReadOnly(true);
ui->le_Lon->setReadOnly(true);
m_weatherUpdateTimer.start(); m_weatherUpdateTimer.start();
updateWeatherInformation();
} }
else else
{ {
m_weatherUpdateTimer.stop(); m_weatherUpdateTimer.stop();
ui->le_LatOrIcao->setReadOnly(false);
ui->le_LatOrIcao->setText({});
ui->le_Lon->setReadOnly(false);
ui->le_Lon->setText({});
updateWeatherInformation();
} }
updateWeatherInformation();
} }
void CWeatherComponent::toggleWeatherActivation() void CWeatherComponent::toggleWeatherActivation()
@@ -129,16 +126,34 @@ namespace BlackGui
sGui->getIContextSimulator()->setWeatherActivated(m_isWeatherActivated); sGui->getIContextSimulator()->setWeatherActivated(m_isWeatherActivated);
} }
void CWeatherComponent::showCoordinateDialog()
{
m_coordinateDialog->show();
}
void CWeatherComponent::setWeatherScenario(int index) void CWeatherComponent::setWeatherScenario(int index)
{ {
if (index == -1) { return; } if (index == -1) { return; }
m_lastOwnAircraftPosition = {}; m_lastOwnAircraftPosition = {};
auto scenario = m_weatherScenarios[index]; CWeatherScenario scenario = m_weatherScenarios[index];
m_weatherScenarioSetting.set(scenario); m_weatherScenarioSetting.set(scenario);
updateWeatherInformation(); updateWeatherInformation();
} }
void CWeatherComponent::setCavok()
{
for (int index = 0; index < m_weatherScenarios.size(); index++)
{
if (m_weatherScenarios[index].getIndex() == CWeatherScenario::ClearSky)
{
// call queued
QTimer::singleShot(0, this, [ = ] { this->setWeatherScenario(index); });
break;
}
}
}
void CWeatherComponent::updateWeatherInformation() void CWeatherComponent::updateWeatherInformation()
{ {
setWeatherGrid({}); setWeatherGrid({});
@@ -151,42 +166,10 @@ namespace BlackGui
{ {
Q_ASSERT(sGui->getIContextOwnAircraft()); Q_ASSERT(sGui->getIContextOwnAircraft());
position = sGui->getIContextOwnAircraft()->getOwnAircraft().getPosition(); position = sGui->getIContextOwnAircraft()->getOwnAircraft().getPosition();
if (position == CCoordinateGeodetic())
{
ui->le_LatOrIcao->setText("N/A");
ui->le_Lon->setText("N/A");
return;
}
ui->le_LatOrIcao->setText(position.latitude().toQString());
ui->le_Lon->setText(position.longitude().toQString());
} }
else else
{ {
QString latitudeOrIcao = ui->le_LatOrIcao->text(); position = m_coordinateDialog->getCoordinate();
QString longitude = ui->le_Lon->text();
const QRegularExpression reIcao("^[a-zA-Z]{4}$", QRegularExpression::CaseInsensitiveOption);
auto icaoMatch = reIcao.match(latitudeOrIcao);
if (icaoMatch.hasMatch())
{
CLogMessage(this).warning("Requested weather for ICAO station %1. Unfortunately ICAO support is not yet implemented.") << latitudeOrIcao;
return;
}
const QRegularExpression reDecimalNumber("^-?\\d{1,2}[,.]?\\d+$", QRegularExpression::CaseInsensitiveOption);
auto latitudeMatch = reDecimalNumber.match(latitudeOrIcao);
auto longitudeMatch = reDecimalNumber.match(longitude);
if (!latitudeMatch.hasMatch() || !longitudeMatch.hasMatch())
{
CLogMessage(this).warning("Invalid position - Latitude: %1, Longitude: %2") << latitudeOrIcao << longitude;
return;
}
// Replace ',' with '.'. Both are allowed as input, but QString::toDouble() only accepts '.'
latitudeOrIcao = latitudeOrIcao.replace(',', '.');
longitude = longitude.replace(',', '.');
position = { latitudeOrIcao.toDouble(), longitude.toDouble(), 0 };
} }
if (CWeatherScenario::isRealWeatherScenario(scenario)) if (CWeatherScenario::isRealWeatherScenario(scenario))
@@ -207,7 +190,7 @@ namespace BlackGui
void CWeatherComponent::weatherGridReceived(const CWeatherGrid &weatherGrid, const CIdentifier &identifier) void CWeatherComponent::weatherGridReceived(const CWeatherGrid &weatherGrid, const CIdentifier &identifier)
{ {
if (!isMyIdentifier(identifier)) { return; } if (!isMyIdentifier(identifier)) { return; }
ui->lb_Status->setText({}); ui->lbl_Status->setText({});
setWeatherGrid(weatherGrid); setWeatherGrid(weatherGrid);
} }
@@ -216,8 +199,7 @@ namespace BlackGui
// UI connections // UI connections
connect(ui->cb_weatherScenario, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), connect(ui->cb_weatherScenario, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this, &CWeatherComponent::setWeatherScenario); this, &CWeatherComponent::setWeatherScenario);
connect(ui->le_LatOrIcao, &QLineEdit::returnPressed, this, &CWeatherComponent::updateWeatherInformation); connect(m_coordinateDialog.data(), &CCoordinateDialog::changedCoordinate, this, &CWeatherComponent::updateWeatherInformation);
connect(ui->le_Lon, &QLineEdit::returnPressed, this, &CWeatherComponent::updateWeatherInformation);
connect(ui->cb_UseOwnAcftPosition, &QCheckBox::toggled, this, &CWeatherComponent::toggleUseOwnAircraftPosition); connect(ui->cb_UseOwnAcftPosition, &QCheckBox::toggled, this, &CWeatherComponent::toggleUseOwnAircraftPosition);
connect(&m_weatherUpdateTimer, &QTimer::timeout, this, &CWeatherComponent::updateWeatherInformation); connect(&m_weatherUpdateTimer, &QTimer::timeout, this, &CWeatherComponent::updateWeatherInformation);
connect(ui->pb_ActivateWeather, &QPushButton::clicked, this, &CWeatherComponent::toggleWeatherActivation); connect(ui->pb_ActivateWeather, &QPushButton::clicked, this, &CWeatherComponent::toggleWeatherActivation);
@@ -227,25 +209,6 @@ namespace BlackGui
connect(sGui->getIContextSimulator(), &IContextSimulator::weatherGridReceived, this, &CWeatherComponent::weatherGridReceived); connect(sGui->getIContextSimulator(), &IContextSimulator::weatherGridReceived, this, &CWeatherComponent::weatherGridReceived);
} }
void CWeatherComponent::setupInputValidators()
{
QRegularExpression reIcaoOrLatitude("^[a-zA-Z]{4}|-?\\d{1,2}[,.]?\\d+$", QRegularExpression::CaseInsensitiveOption);
ui->le_LatOrIcao->setValidator(new QRegularExpressionValidator(reIcaoOrLatitude, this));
QRegularExpression reLongitude("^-?\\d{1,2}[,.]?\\d+$", QRegularExpression::CaseInsensitiveOption);
ui->le_Lon->setValidator(new QRegularExpressionValidator(reLongitude, this));
}
void CWeatherComponent::setupCompleter()
{
// Temporary list of ICAO airports. Replace with final list, once available
QStringList airports = { "EDDM", "LSZH", "EDMO", "EGLL" };
QCompleter *c = new QCompleter(airports, this);
c->setCaseSensitivity(Qt::CaseInsensitive);
c->setCompletionMode(QCompleter::PopupCompletion);
c->setMaxVisibleItems(5);
ui->le_LatOrIcao->setCompleter(c);
}
void CWeatherComponent::setWeatherGrid(const CWeatherGrid &weatherGrid) void CWeatherComponent::setWeatherGrid(const CWeatherGrid &weatherGrid)
{ {
auto gridPoint = weatherGrid.frontOrDefault(); auto gridPoint = weatherGrid.frontOrDefault();
@@ -256,11 +219,10 @@ namespace BlackGui
void CWeatherComponent::requestWeatherGrid(const CCoordinateGeodetic &position) void CWeatherComponent::requestWeatherGrid(const CCoordinateGeodetic &position)
{ {
ui->lb_Status->setText("Loading..."); ui->lbl_Status->setText("Loading...");
CWeatherGrid weatherGrid { { {}, position } }; CWeatherGrid weatherGrid { { {}, position } };
auto ident = identifier(); auto ident = identifier();
sGui->getIContextSimulator()->requestWeatherGrid(weatherGrid, ident); sGui->getIContextSimulator()->requestWeatherGrid(weatherGrid, ident);
} }
} // namespace } // namespace
} // namespace } // namespace

View File

@@ -12,7 +12,8 @@
#ifndef BLACKGUI_WEATHERCOMPONENT_H #ifndef BLACKGUI_WEATHERCOMPONENT_H
#define BLACKGUI_WEATHERCOMPONENT_H #define BLACKGUI_WEATHERCOMPONENT_H
#include "blackgui/components/enablefordockwidgetinfoarea.h" #include "enablefordockwidgetinfoarea.h"
#include "coordinatedialog.h"
#include "blackgui/blackguiexport.h" #include "blackgui/blackguiexport.h"
#include "blackcore/actionbind.h" #include "blackcore/actionbind.h"
#include "blackmisc/geo/coordinategeodetic.h" #include "blackmisc/geo/coordinategeodetic.h"
@@ -35,6 +36,7 @@ namespace Ui { class CWeatherComponent; }
namespace BlackGui namespace BlackGui
{ {
class CDockWidgetInfoArea; class CDockWidgetInfoArea;
namespace Components namespace Components
{ {
//! Weather component //! Weather component
@@ -55,30 +57,30 @@ namespace BlackGui
//! \copydoc CEnableForDockWidgetInfoArea::setParentDockWidgetInfoArea //! \copydoc CEnableForDockWidgetInfoArea::setParentDockWidgetInfoArea
virtual bool setParentDockWidgetInfoArea(BlackGui::CDockWidgetInfoArea *parentDockableWidget) override; virtual bool setParentDockWidgetInfoArea(BlackGui::CDockWidgetInfoArea *parentDockableWidget) override;
private slots:
void ps_infoAreaTabBarChanged(int index);
private: private:
void toggleUseOwnAircraftPosition(bool checked); void infoAreaTabBarChanged(int index);
void toggleUseOwnAircraftPosition(bool useOwnAircraftPosition);
void toggleWeatherActivation(); void toggleWeatherActivation();
void showCoordinateDialog();
void setWeatherScenario(int index); void setWeatherScenario(int index);
void setCavok();
void updateWeatherInformation(); void updateWeatherInformation();
void weatherGridReceived(const BlackMisc::Weather::CWeatherGrid &weatherGrid, const BlackMisc::CIdentifier &identifier); void weatherGridReceived(const BlackMisc::Weather::CWeatherGrid &weatherGrid, const BlackMisc::CIdentifier &identifier);
void setupConnections(); void setupConnections();
void setupInputValidators();
void setupCompleter();
void setWeatherGrid(const BlackMisc::Weather::CWeatherGrid &weatherGrid); void setWeatherGrid(const BlackMisc::Weather::CWeatherGrid &weatherGrid);
void requestWeatherGrid(const BlackMisc::Geo::CCoordinateGeodetic &position); void requestWeatherGrid(const BlackMisc::Geo::CCoordinateGeodetic &position);
QScopedPointer<Ui::CWeatherComponent> ui; QScopedPointer<Ui::CWeatherComponent> ui;
QScopedPointer<CCoordinateDialog> m_coordinateDialog { new CCoordinateDialog(this) };
QVector<BlackMisc::Weather::CWeatherScenario> m_weatherScenarios; QVector<BlackMisc::Weather::CWeatherScenario> m_weatherScenarios;
QTimer m_weatherUpdateTimer { this }; QTimer m_weatherUpdateTimer { this };
BlackMisc::Geo::CCoordinateGeodetic m_lastOwnAircraftPosition; BlackMisc::Geo::CCoordinateGeodetic m_lastOwnAircraftPosition;
BlackMisc::CSetting<BlackMisc::Simulation::Settings::TSelectedWeatherScenario> m_weatherScenarioSetting { this }; BlackMisc::CSetting<BlackMisc::Simulation::Settings::TSelectedWeatherScenario> m_weatherScenarioSetting { this };
BlackCore::CActionBindings m_hotkeyBindings; BlackCore::CActionBindings m_hotkeyBindings; //!< allow binding of hotkey
bool m_isWeatherActivated = false; bool m_isWeatherActivated = false;
}; };
} // namespace } // namespace

View File

@@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>400</width> <width>280</width>
<height>556</height> <height>396</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@@ -21,7 +21,7 @@
<number>3</number> <number>3</number>
</property> </property>
<property name="topMargin"> <property name="topMargin">
<number>7</number> <number>3</number>
</property> </property>
<property name="rightMargin"> <property name="rightMargin">
<number>3</number> <number>3</number>
@@ -53,8 +53,23 @@
<property name="title"> <property name="title">
<string>Weather Display</string> <string>Weather Display</string>
</property> </property>
<layout class="QGridLayout" name="gl_weatherDisplay"> <layout class="QVBoxLayout" name="vl_WeatherDisplay">
<item row="0" column="0" colspan="2"> <property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item>
<widget class="QFrame" name="fr_Misc">
<layout class="QHBoxLayout" name="hl_Misc">
<item>
<widget class="QCheckBox" name="cb_UseOwnAcftPosition"> <widget class="QCheckBox" name="cb_UseOwnAcftPosition">
<property name="text"> <property name="text">
<string>Use own aircraft position</string> <string>Use own aircraft position</string>
@@ -64,63 +79,25 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item alignment="Qt::AlignRight">
<widget class="QLineEdit" name="le_LatOrIcao"> <widget class="QPushButton" name="pb_Coordinate">
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="placeholderText">
<string>latitude or ICAO</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="le_Lon">
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="placeholderText">
<string>longitude</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="lb_Status">
<property name="text"> <property name="text">
<string/> <string>coordinate</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="3"> </layout>
<spacer name="horizontalSpacer"> </widget>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item> </item>
<item row="2" column="0" colspan="4"> <item>
<widget class="QTabWidget" name="tw_weatherGrid"> <widget class="QLabel" name="lbl_Status">
<property name="currentIndex"> <property name="text">
<number>0</number> <string>&lt;status will go here&gt;</string>
</property> </property>
</widget>
</item>
<item>
<widget class="QTabWidget" name="tw_weatherGrid">
<widget class="QWidget" name="tb_temperatureLayers"> <widget class="QWidget" name="tb_temperatureLayers">
<attribute name="title"> <attribute name="title">
<string>Temperature</string> <string>Temperature</string>

View File

@@ -39,7 +39,7 @@ namespace BlackMisc
//! Properties by index //! Properties by index
enum ColumnIndex enum ColumnIndex
{ {
IndexScenarioIndex = BlackMisc::CPropertyIndex::GlobalIndexCWeatherScenario, IndexScenarioIndex = CPropertyIndex::GlobalIndexCWeatherScenario,
IndexScenarioName, IndexScenarioName,
IndexScenarioDescription IndexScenarioDescription
}; };
@@ -95,7 +95,6 @@ namespace BlackMisc
BLACK_METAMEMBER(scenarioDescription) BLACK_METAMEMBER(scenarioDescription)
); );
}; };
} //namespace } //namespace
} // namespace } // namespace