supercell-wx/scwx-qt/source/scwx/qt/main/main_window.cpp

1658 lines
53 KiB
C++

#include "main_window.hpp"
#include "./ui_main_window.h"
#include <scwx/qt/gl/gl_context.hpp>
#include <scwx/qt/main/application.hpp>
#include <scwx/qt/main/versions.hpp>
#include <scwx/qt/manager/alert_manager.hpp>
#include <scwx/qt/manager/hotkey_manager.hpp>
#include <scwx/qt/manager/placefile_manager.hpp>
#include <scwx/qt/manager/marker_manager.hpp>
#include <scwx/qt/manager/position_manager.hpp>
#include <scwx/qt/manager/radar_product_manager.hpp>
#include <scwx/qt/manager/text_event_manager.hpp>
#include <scwx/qt/manager/timeline_manager.hpp>
#include <scwx/qt/manager/update_manager.hpp>
#include <scwx/qt/map/map_provider.hpp>
#include <scwx/qt/map/map_widget.hpp>
#include <scwx/qt/model/layer_model.hpp>
#include <scwx/qt/model/radar_site_model.hpp>
#include <scwx/qt/settings/general_settings.hpp>
#include <scwx/qt/settings/map_settings.hpp>
#include <scwx/qt/settings/ui_settings.hpp>
#include <scwx/qt/ui/about_dialog.hpp>
#include <scwx/qt/ui/alert_dock_widget.hpp>
#include <scwx/qt/ui/animation_dock_widget.hpp>
#include <scwx/qt/ui/collapsible_group.hpp>
#include <scwx/qt/ui/flow_layout.hpp>
#include <scwx/qt/ui/gps_info_dialog.hpp>
#include <scwx/qt/ui/imgui_debug_dialog.hpp>
#include <scwx/qt/ui/layer_dialog.hpp>
#include <scwx/qt/ui/level2_products_widget.hpp>
#include <scwx/qt/ui/level2_settings_widget.hpp>
#include <scwx/qt/ui/level3_products_widget.hpp>
#include <scwx/qt/ui/placefile_dialog.hpp>
#include <scwx/qt/ui/marker_dialog.hpp>
#include <scwx/qt/ui/radar_site_dialog.hpp>
#include <scwx/qt/ui/settings_dialog.hpp>
#include <scwx/qt/ui/update_dialog.hpp>
#include <scwx/common/characters.hpp>
#include <scwx/common/products.hpp>
#include <scwx/common/vcp.hpp>
#include <scwx/util/logger.hpp>
#include <scwx/util/time.hpp>
#include <set>
#include <boost/asio/post.hpp>
#include <boost/asio/thread_pool.hpp>
#include <QDesktopServices>
#include <QKeyEvent>
#include <QFileDialog>
#include <QMessageBox>
#include <QSplitter>
#include <QStandardPaths>
#include <QTimer>
#include <QToolButton>
namespace scwx
{
namespace qt
{
namespace main
{
static const std::string logPrefix_ = "scwx::qt::main::main_window";
static const auto logger_ = util::Logger::Create(logPrefix_);
class MainWindowImpl : public QObject
{
Q_OBJECT
public:
explicit MainWindowImpl(MainWindow* mainWindow) :
mainWindow_ {mainWindow},
settings_ {},
activeMap_ {nullptr},
mapSettingsGroup_ {nullptr},
level2ProductsGroup_ {nullptr},
level2SettingsGroup_ {nullptr},
level3ProductsGroup_ {nullptr},
timelineGroup_ {nullptr},
level2ProductsWidget_ {nullptr},
level2SettingsWidget_ {nullptr},
level3ProductsWidget_ {nullptr},
alertDockWidget_ {nullptr},
animationDockWidget_ {nullptr},
aboutDialog_ {nullptr},
gpsInfoDialog_ {nullptr},
imGuiDebugDialog_ {nullptr},
layerDialog_ {nullptr},
placefileDialog_ {nullptr},
markerDialog_ {nullptr},
radarSiteDialog_ {nullptr},
settingsDialog_ {nullptr},
updateDialog_ {nullptr},
alertManager_ {manager::AlertManager::Instance()},
placefileManager_ {manager::PlacefileManager::Instance()},
markerManager_ {manager::MarkerManager::Instance()},
positionManager_ {manager::PositionManager::Instance()},
textEventManager_ {manager::TextEventManager::Instance()},
timelineManager_ {manager::TimelineManager::Instance()},
updateManager_ {manager::UpdateManager::Instance()},
maps_ {}
{
mapProvider_ = map::GetMapProvider(
settings::GeneralSettings::Instance().map_provider().GetValue());
const map::MapProviderInfo& mapProviderInfo =
map::GetMapProviderInfo(mapProvider_);
std::string appDataPath {
QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)
.toStdString()};
std::string cacheDbPath {appDataPath + "/" +
mapProviderInfo.cacheDbName_};
if (!std::filesystem::exists(appDataPath))
{
if (!std::filesystem::create_directories(appDataPath))
{
logger_->error(
"Unable to create application local data directory: \"{}\"",
appDataPath);
}
}
std::string mapProviderApiKey = map::GetMapProviderApiKey(mapProvider_);
if (mapProvider_ == map::MapProvider::Mapbox)
{
settings_.setProviderTemplate(mapProviderInfo.providerTemplate_);
settings_.setApiKey(QString {mapProviderApiKey.c_str()});
}
settings_.setCacheDatabasePath(QString {cacheDbPath.c_str()});
settings_.setCacheDatabaseMaximumSize(20 * 1024 * 1024);
if (settings::GeneralSettings::Instance().track_location().GetValue())
{
positionManager_->TrackLocation(true);
}
}
~MainWindowImpl()
{
homeRadarConnection_.disconnect();
defaultTimeZoneConnection_.disconnect();
auto& generalSettings = settings::GeneralSettings::Instance();
auto& customStyleUrl = generalSettings.custom_style_url();
auto& customStyleDrawLayer = generalSettings.custom_style_draw_layer();
customStyleUrl.UnregisterValueChangedCallback(
customStyleUrlChangedCallbackUuid_);
customStyleDrawLayer.UnregisterValueChangedCallback(
customStyleDrawLayerChangedCallbackUuid_);
clockTimer_.stop();
threadPool_.join();
}
void AddRadarSitePreset(const std::string& id);
void AsyncSetup();
void ConfigureMapLayout();
void ConfigureMapStyles();
void ConfigureUiSettings();
void ConnectAnimationSignals();
void ConnectMapSignals();
void ConnectOtherSignals();
void HandleFocusChange(QWidget* focused);
void InitializeLayerDisplayActions();
void PopulateCustomMapStyle();
void PopulateMapStyles();
void SelectElevation(map::MapWidget* mapWidget, float elevation);
void SelectRadarProduct(map::MapWidget* mapWidget,
common::RadarProductGroup group,
const std::string& productName,
int16_t productCode);
void SetActiveMap(map::MapWidget* mapWidget);
void UpdateAvailableLevel3Products();
void UpdateElevationSelection(float elevation);
void UpdateMapStyle(const std::string& styleName);
void UpdateRadarProductSelection(common::RadarProductGroup group,
const std::string& product);
void UpdateRadarProductSettings();
void UpdateRadarSite();
void UpdateVcp();
boost::asio::thread_pool threadPool_ {1u};
MainWindow* mainWindow_;
QMapLibre::Settings settings_;
map::MapProvider mapProvider_;
map::MapWidget* activeMap_;
std::shared_ptr<gl::GlContext> glContext_ {nullptr};
ui::CollapsibleGroup* mapSettingsGroup_;
ui::CollapsibleGroup* level2ProductsGroup_;
ui::CollapsibleGroup* level2SettingsGroup_;
ui::CollapsibleGroup* level3ProductsGroup_;
ui::CollapsibleGroup* timelineGroup_;
ui::Level2ProductsWidget* level2ProductsWidget_;
ui::Level2SettingsWidget* level2SettingsWidget_;
ui::Level3ProductsWidget* level3ProductsWidget_;
QLabel* coordinateLabel_ {nullptr};
QLabel* timeLabel_ {nullptr};
ui::AlertDockWidget* alertDockWidget_;
ui::AnimationDockWidget* animationDockWidget_;
ui::AboutDialog* aboutDialog_;
ui::GpsInfoDialog* gpsInfoDialog_;
ui::ImGuiDebugDialog* imGuiDebugDialog_;
ui::LayerDialog* layerDialog_;
ui::PlacefileDialog* placefileDialog_;
ui::MarkerDialog* markerDialog_;
ui::RadarSiteDialog* radarSiteDialog_;
ui::SettingsDialog* settingsDialog_;
ui::UpdateDialog* updateDialog_;
QTimer clockTimer_ {};
bool customStyleAvailable_ {false};
boost::uuids::uuid customStyleDrawLayerChangedCallbackUuid_ {};
boost::uuids::uuid customStyleUrlChangedCallbackUuid_ {};
std::shared_ptr<manager::AlertManager> alertManager_;
std::shared_ptr<manager::HotkeyManager> hotkeyManager_ {
manager::HotkeyManager::Instance()};
std::shared_ptr<manager::PlacefileManager> placefileManager_;
std::shared_ptr<manager::MarkerManager> markerManager_;
std::shared_ptr<manager::PositionManager> positionManager_;
std::shared_ptr<manager::TextEventManager> textEventManager_;
std::shared_ptr<manager::TimelineManager> timelineManager_;
std::shared_ptr<manager::UpdateManager> updateManager_;
std::shared_ptr<model::LayerModel> layerModel_ {
model::LayerModel::Instance()};
std::shared_ptr<model::RadarSiteModel> radarSiteModel_ {
model::RadarSiteModel::Instance()};
std::map<std::string, std::shared_ptr<QAction>> radarSitePresetsActions_ {};
QMenu* radarSitePresetsMenu_ {nullptr};
std::set<std::tuple<types::LayerType, types::LayerDescription, QAction*>>
layerActions_ {};
bool layerActionsInitialized_ {false};
boost::signals2::scoped_connection homeRadarConnection_ {};
boost::signals2::scoped_connection defaultTimeZoneConnection_ {};
std::vector<map::MapWidget*> maps_;
std::chrono::system_clock::time_point selectedTime_ {};
public slots:
void UpdateMapParameters(double latitude,
double longitude,
double zoom,
double bearing,
double pitch);
};
MainWindow::MainWindow(QWidget* parent) :
QMainWindow(parent),
p(std::make_unique<MainWindowImpl>(this)),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
p->InitializeLayerDisplayActions();
// Assign the bottom left corner to the left dock widget
setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
// Configure Radar Site Box
ui->vcpLabel->setVisible(false);
ui->vcpValueLabel->setVisible(false);
ui->vcpDescriptionLabel->setVisible(false);
ui->saveRadarProductsButton->setVisible(true);
p->radarSitePresetsMenu_ = new QMenu(this);
ui->radarSitePresetsButton->setMenu(p->radarSitePresetsMenu_);
auto radarSitePresets = p->radarSiteModel_->presets();
for (auto& preset : radarSitePresets)
{
p->AddRadarSitePreset(preset);
}
ui->radarSitePresetsButton->setVisible(!radarSitePresets.empty());
// Configure Alert Dock
p->alertDockWidget_ = new ui::AlertDockWidget(this);
addDockWidget(Qt::BottomDockWidgetArea, p->alertDockWidget_);
// GPS Info Dialog
p->gpsInfoDialog_ = new ui::GpsInfoDialog(this);
// Configure Menu
ui->menuView->insertAction(ui->actionRadarToolbox,
ui->radarToolboxDock->toggleViewAction());
ui->radarToolboxDock->toggleViewAction()->setText(tr("Radar &Toolbox"));
ui->actionRadarToolbox->setVisible(false);
ui->menuView->insertAction(ui->actionAlerts,
p->alertDockWidget_->toggleViewAction());
p->alertDockWidget_->toggleViewAction()->setText(tr("&Alerts"));
ui->actionAlerts->setVisible(false);
ui->menuDebug->menuAction()->setVisible(
settings::GeneralSettings::Instance().debug_enabled().GetValue());
// Configure Map
p->ConfigureMapLayout();
// Radar Site Dialog
p->radarSiteDialog_ = new ui::RadarSiteDialog(this);
// Placefile Manager Dialog
p->placefileDialog_ = new ui::PlacefileDialog(this);
// Marker Manager Dialog
p->markerDialog_ = new ui::MarkerDialog(this);
// Layer Dialog
p->layerDialog_ = new ui::LayerDialog(this);
// Settings Dialog
p->settingsDialog_ = new ui::SettingsDialog(p->settings_, this);
// Map Settings
p->mapSettingsGroup_ = new ui::CollapsibleGroup(tr("Map Settings"), this);
p->mapSettingsGroup_->GetContentsLayout()->addWidget(ui->mapStyleLabel);
p->mapSettingsGroup_->GetContentsLayout()->addWidget(ui->mapStyleComboBox);
p->mapSettingsGroup_->GetContentsLayout()->addWidget(
ui->smoothRadarDataCheckBox);
p->mapSettingsGroup_->GetContentsLayout()->addWidget(
ui->trackLocationCheckBox);
p->mapSettingsGroup_->GetContentsLayout()->addWidget(
ui->saveRadarProductsButton);
ui->radarToolboxScrollAreaContents->layout()->replaceWidget(
ui->mapSettingsGroupBox, p->mapSettingsGroup_);
ui->mapSettingsGroupBox->setVisible(false);
ui->trackLocationCheckBox->setChecked(
settings::GeneralSettings::Instance().track_location().GetValue());
// Add Level 2 Products
p->level2ProductsGroup_ =
new ui::CollapsibleGroup(tr("Level 2 Products"), this);
p->level2ProductsWidget_ = new ui::Level2ProductsWidget(this);
p->level2ProductsGroup_->GetContentsLayout()->addWidget(
p->level2ProductsWidget_);
ui->radarToolboxScrollAreaContents->layout()->addWidget(
p->level2ProductsGroup_);
// Add Level 3 Products
p->level3ProductsGroup_ =
new ui::CollapsibleGroup(tr("Level 3 Products"), this);
p->level3ProductsWidget_ = new ui::Level3ProductsWidget(this);
p->level3ProductsGroup_->GetContentsLayout()->addWidget(
p->level3ProductsWidget_);
ui->radarToolboxScrollAreaContents->layout()->addWidget(
p->level3ProductsGroup_);
// Add Level 2 Settings
p->level2SettingsGroup_ =
new ui::CollapsibleGroup(tr("Level 2 Settings"), this);
p->level2SettingsWidget_ = new ui::Level2SettingsWidget(this);
p->level2SettingsGroup_->GetContentsLayout()->addWidget(
p->level2SettingsWidget_);
ui->radarToolboxScrollAreaContents->layout()->addWidget(
p->level2SettingsGroup_);
p->level2SettingsGroup_->setVisible(false);
ui->radarToolboxScrollAreaContents->layout()->addWidget(
p->level2SettingsGroup_);
// Timeline
p->timelineGroup_ = new ui::CollapsibleGroup(tr("Timeline"), this);
p->animationDockWidget_ = new ui::AnimationDockWidget(this);
p->timelineGroup_->GetContentsLayout()->addWidget(p->animationDockWidget_);
ui->radarToolboxScrollAreaContents->layout()->addWidget(p->timelineGroup_);
p->animationDockWidget_->UpdateTimeZone(p->activeMap_->GetDefaultTimeZone());
// Reset toolbox spacer at the bottom
ui->radarToolboxScrollAreaContents->layout()->removeItem(
ui->radarToolboxSpacer);
ui->radarToolboxScrollAreaContents->layout()->addItem(
ui->radarToolboxSpacer);
// Status Bar
QWidget* statusBarWidget = new QWidget(this);
p->coordinateLabel_ = new QLabel(this);
p->coordinateLabel_->setFrameShape(QFrame::Shape::Box);
p->coordinateLabel_->setFrameShadow(QFrame::Shadow::Sunken);
p->coordinateLabel_->setVisible(false);
p->timeLabel_ = new QLabel(this);
p->timeLabel_->setFrameShape(QFrame::Shape::Box);
p->timeLabel_->setFrameShadow(QFrame::Shadow::Sunken);
p->timeLabel_->setVisible(false);
QGridLayout* statusBarLayout = new QGridLayout(statusBarWidget);
statusBarLayout->setContentsMargins(0, 0, 0, 0);
statusBarLayout->addWidget(p->coordinateLabel_, 0, 0);
statusBarLayout->addWidget(p->timeLabel_, 0, 1);
ui->statusbar->addPermanentWidget(statusBarWidget);
// ImGui Debug Dialog
p->imGuiDebugDialog_ = new ui::ImGuiDebugDialog(this);
// About Dialog
p->aboutDialog_ = new ui::AboutDialog(this);
// Update Dialog
p->updateDialog_ = new ui::UpdateDialog(this);
auto& mapSettings = settings::MapSettings::Instance();
for (size_t i = 0; i < p->maps_.size(); i++)
{
p->SelectRadarProduct(p->maps_.at(i),
common::GetRadarProductGroup(
mapSettings.radar_product_group(i).GetValue()),
mapSettings.radar_product(i).GetValue(),
0);
}
p->PopulateMapStyles();
p->ConfigureMapStyles();
p->ConfigureUiSettings();
p->ConnectMapSignals();
p->ConnectAnimationSignals();
p->ConnectOtherSignals();
p->HandleFocusChange(p->activeMap_);
p->AsyncSetup();
Application::FinishInitialization();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::keyPressEvent(QKeyEvent* ev)
{
if (p->hotkeyManager_->HandleKeyPress(ev))
{
p->activeMap_->update();
ev->accept();
}
}
void MainWindow::keyReleaseEvent(QKeyEvent* ev)
{
if (p->hotkeyManager_->HandleKeyRelease(ev))
{
p->activeMap_->update();
ev->accept();
}
}
void MainWindow::showEvent(QShowEvent* event)
{
QMainWindow::showEvent(event);
static bool firstShowEvent = true;
bool restored = false;
if (firstShowEvent)
{
auto& uiSettings = settings::UiSettings::Instance();
// restore the geometry state
std::string uiGeometry = uiSettings.main_ui_geometry().GetValue();
restoreGeometry(
QByteArray::fromBase64(QByteArray::fromStdString(uiGeometry)));
// restore the UI state
std::string uiState = uiSettings.main_ui_state().GetValue();
restored = restoreState(
QByteArray::fromBase64(QByteArray::fromStdString(uiState)));
firstShowEvent = false;
}
if (!restored)
{
resizeDocks({ui->radarToolboxDock}, {194}, Qt::Horizontal);
}
}
void MainWindow::closeEvent(QCloseEvent* event)
{
auto& uiSettings = settings::UiSettings::Instance();
// save the UI geometry
QByteArray uiGeometry = saveGeometry().toBase64();
uiSettings.main_ui_geometry().StageValue(uiGeometry.data());
// save the UI state
QByteArray uiState = saveState().toBase64();
uiSettings.main_ui_state().StageValue(uiState.data());
QMainWindow::closeEvent(event);
}
void MainWindow::on_actionOpenNexrad_triggered()
{
static const std::string nexradFilter = "NEXRAD Products (*)";
QFileDialog* dialog = new QFileDialog(this);
dialog->setFileMode(QFileDialog::ExistingFile);
dialog->setNameFilter(tr(nexradFilter.c_str()));
dialog->setAttribute(Qt::WA_DeleteOnClose);
map::MapWidget* currentMap = p->activeMap_;
// Make sure the parent window properly repaints on close
connect(dialog,
&QFileDialog::finished,
this,
static_cast<void (MainWindow::*)()>(&MainWindow::update),
Qt::QueuedConnection);
connect(
dialog,
&QFileDialog::fileSelected,
this,
[=, this](const QString& file)
{
logger_->info("Selected: {}", file.toStdString());
auto radarSite = p->activeMap_->GetRadarSite();
std::string currentRadarSite =
(radarSite != nullptr) ? radarSite->id() : std::string {};
std::shared_ptr<request::NexradFileRequest> request =
std::make_shared<request::NexradFileRequest>(currentRadarSite);
connect( //
request.get(),
&request::NexradFileRequest::RequestComplete,
this,
[=, this](std::shared_ptr<request::NexradFileRequest> request)
{
std::shared_ptr<types::RadarProductRecord> record =
request->radar_product_record();
if (record != nullptr)
{
currentMap->SetAutoRefresh(false);
currentMap->SelectRadarProduct(record);
}
else
{
QMessageBox* messageBox = new QMessageBox(this);
messageBox->setIcon(QMessageBox::Warning);
messageBox->setText(
QString("%1\n%2").arg(tr("Unrecognized NEXRAD Product:"),
QDir::toNativeSeparators(file)));
messageBox->setAttribute(Qt::WA_DeleteOnClose);
messageBox->open();
}
});
manager::RadarProductManager::LoadFile(file.toStdString(), request);
});
dialog->open();
}
void MainWindow::on_actionOpenTextEvent_triggered()
{
static const std::string textFilter = "Text Event Products (*.txt)";
static const std::string allFilter = "All Files (*)";
QFileDialog* dialog = new QFileDialog(this);
dialog->setFileMode(QFileDialog::ExistingFile);
dialog->setNameFilters({tr(textFilter.c_str()), tr(allFilter.c_str())});
dialog->setAttribute(Qt::WA_DeleteOnClose);
// Make sure the parent window properly repaints on close
connect(dialog,
&QFileDialog::finished,
this,
static_cast<void (MainWindow::*)()>(&MainWindow::update),
Qt::QueuedConnection);
connect(dialog,
&QFileDialog::fileSelected,
this,
[this](const QString& file)
{
logger_->info("Selected: {}", file.toStdString());
p->textEventManager_->LoadFile(file.toStdString());
});
dialog->open();
}
void MainWindow::on_actionSettings_triggered()
{
p->settingsDialog_->show();
}
void MainWindow::on_actionExit_triggered()
{
close();
}
void MainWindow::on_actionGpsInfo_triggered()
{
p->gpsInfoDialog_->show();
}
void MainWindow::on_actionColorTable_triggered(bool checked)
{
p->layerModel_->SetLayerDisplayed(types::LayerType::Information,
types::InformationLayer::ColorTable,
checked);
}
void MainWindow::on_actionRadarRange_triggered(bool checked)
{
p->layerModel_->SetLayerDisplayed(
types::LayerType::Data, types::DataLayer::RadarRange, checked);
}
void MainWindow::on_actionRadarSites_triggered(bool checked)
{
p->layerModel_->SetLayerDisplayed(types::LayerType::Information,
types::InformationLayer::RadarSite,
checked);
}
void MainWindow::on_actionPlacefileManager_triggered()
{
p->placefileDialog_->show();
}
void MainWindow::on_actionMarkerManager_triggered()
{
p->markerDialog_->show();
}
void MainWindow::on_actionLayerManager_triggered()
{
p->layerDialog_->show();
}
void MainWindow::on_actionImGuiDebug_triggered()
{
p->imGuiDebugDialog_->show();
}
void MainWindow::on_actionDumpLayerList_triggered()
{
p->activeMap_->DumpLayerList();
}
void MainWindow::on_actionDumpRadarProductRecords_triggered()
{
manager::RadarProductManager::DumpRecords();
}
void MainWindow::on_actionRadarWireframe_triggered(bool checked)
{
p->activeMap_->SetRadarWireframeEnabled(checked);
}
void MainWindow::on_actionUserManual_triggered()
{
QDesktopServices::openUrl(QUrl {"https://supercell-wx.readthedocs.io/"});
}
void MainWindow::on_actionDiscord_triggered()
{
QDesktopServices::openUrl(QUrl {"https://discord.gg/vFMV76brwU"});
}
void MainWindow::on_actionGitHubRepository_triggered()
{
QDesktopServices::openUrl(QUrl {"https://github.com/dpaulat/supercell-wx"});
}
void MainWindow::on_actionCheckForUpdates_triggered()
{
boost::asio::post(
p->threadPool_,
[this]()
{
try
{
if (!p->updateManager_->CheckForUpdates(main::kVersionString_))
{
QMetaObject::invokeMethod(
this,
[this]()
{
QMessageBox* messageBox = new QMessageBox(this);
messageBox->setIcon(QMessageBox::Icon::Information);
messageBox->setWindowTitle(tr("Check for Updates"));
messageBox->setText(tr("Supercell Wx is up to date."));
messageBox->setStandardButtons(
QMessageBox::StandardButton::Ok);
messageBox->show();
});
}
}
catch (const std::exception& ex)
{
logger_->error(ex.what());
}
});
}
void MainWindow::on_actionAboutSupercellWx_triggered()
{
p->aboutDialog_->show();
}
void MainWindow::on_radarSiteHomeButton_clicked()
{
std::string homeRadarSite =
settings::GeneralSettings::Instance().default_radar_site().GetValue();
for (map::MapWidget* map : p->maps_)
{
map->SelectRadarSite(homeRadarSite);
}
p->UpdateRadarSite();
}
void MainWindow::on_radarSiteSelectButton_clicked()
{
p->radarSiteDialog_->show();
}
void MainWindowImpl::AsyncSetup()
{
auto& generalSettings = settings::GeneralSettings::Instance();
// Check for updates
if (generalSettings.update_notifications_enabled().GetValue())
{
boost::asio::post(threadPool_,
[this]()
{
try
{
manager::UpdateManager::RemoveTemporaryReleases();
updateManager_->CheckForUpdates(
main::kVersionString_);
}
catch (const std::exception& ex)
{
logger_->error(ex.what());
}
});
}
}
void MainWindowImpl::ConfigureMapLayout()
{
auto& generalSettings = settings::GeneralSettings::Instance();
const int64_t gridWidth = generalSettings.grid_width().GetValue();
const int64_t gridHeight = generalSettings.grid_height().GetValue();
const int64_t mapCount = gridWidth * gridHeight;
size_t mapIndex = 0;
QSplitter* vs = new QSplitter(Qt::Vertical);
vs->setHandleWidth(1);
maps_.resize(mapCount);
timelineManager_->SetMapCount(mapCount);
auto MoveSplitter = [=, this](int /*pos*/, int /*index*/)
{
QSplitter* s = static_cast<QSplitter*>(sender());
auto sizes = s->sizes();
for (QSplitter* hs : vs->findChildren<QSplitter*>())
{
hs->setSizes(sizes);
}
};
glContext_ = std::make_shared<gl::GlContext>();
for (int64_t y = 0; y < gridHeight; y++)
{
QSplitter* hs = new QSplitter(vs);
hs->setHandleWidth(1);
for (int64_t x = 0; x < gridWidth; x++, mapIndex++)
{
if (maps_.at(mapIndex) == nullptr)
{
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Owned by parent
maps_[mapIndex] =
new map::MapWidget(mapIndex, settings_, glContext_);
}
hs->addWidget(maps_[mapIndex]);
}
connect(hs, &QSplitter::splitterMoved, this, MoveSplitter);
}
mainWindow_->ui->centralwidget->layout()->addWidget(vs);
if (mapCount > 0)
{
SetActiveMap(maps_.at(0));
}
else
{
SetActiveMap(nullptr);
}
}
void MainWindowImpl::ConfigureMapStyles()
{
const auto& mapProviderInfo = map::GetMapProviderInfo(mapProvider_);
auto& mapSettings = settings::MapSettings::Instance();
for (std::size_t i = 0; i < maps_.size(); i++)
{
std::string styleName = mapSettings.map_style(i).GetValue();
if ((customStyleAvailable_ && styleName == "Custom") ||
std::find_if(mapProviderInfo.mapStyles_.cbegin(),
mapProviderInfo.mapStyles_.cend(),
[&](const auto& mapStyle)
{ return mapStyle.name_ == styleName; }) !=
mapProviderInfo.mapStyles_.cend())
{
// Initialize map style from settings
maps_.at(i)->SetInitialMapStyle(styleName);
// Update the active map's style
if (maps_[i] == activeMap_)
{
UpdateMapStyle(styleName);
}
}
else if (!mapProviderInfo.mapStyles_.empty())
{
// Stage first valid map style from map provider
mapSettings.map_style(i).StageValue(
mapProviderInfo.mapStyles_.at(0).name_);
}
}
}
void MainWindowImpl::ConfigureUiSettings()
{
auto& uiSettings = settings::UiSettings::Instance();
level2ProductsGroup_->SetExpanded(
uiSettings.level2_products_expanded().GetValue());
level2SettingsGroup_->SetExpanded(
uiSettings.level2_settings_expanded().GetValue());
level3ProductsGroup_->SetExpanded(
uiSettings.level3_products_expanded().GetValue());
mapSettingsGroup_->SetExpanded(
uiSettings.map_settings_expanded().GetValue());
timelineGroup_->SetExpanded(uiSettings.timeline_expanded().GetValue());
connect(level2ProductsGroup_,
&ui::CollapsibleGroup::StateChanged,
[&](bool expanded)
{ uiSettings.level2_products_expanded().StageValue(expanded); });
connect(level2SettingsGroup_,
&ui::CollapsibleGroup::StateChanged,
[&](bool expanded)
{ uiSettings.level2_settings_expanded().StageValue(expanded); });
connect(level3ProductsGroup_,
&ui::CollapsibleGroup::StateChanged,
[&](bool expanded)
{ uiSettings.level3_products_expanded().StageValue(expanded); });
connect(mapSettingsGroup_,
&ui::CollapsibleGroup::StateChanged,
[&](bool expanded)
{ uiSettings.map_settings_expanded().StageValue(expanded); });
connect(timelineGroup_,
&ui::CollapsibleGroup::StateChanged,
[&](bool expanded)
{ uiSettings.timeline_expanded().StageValue(expanded); });
}
void MainWindowImpl::ConnectMapSignals()
{
for (const auto& mapWidget : maps_)
{
connect(mapWidget,
&map::MapWidget::AlertSelected,
alertDockWidget_,
&ui::AlertDockWidget::SelectAlert);
connect(mapWidget,
&map::MapWidget::MapParametersChanged,
this,
&MainWindowImpl::UpdateMapParameters);
connect(
mapWidget,
&map::MapWidget::MapParametersChanged,
this,
[&](double latitude, double longitude)
{
if (mapWidget == activeMap_)
{
Q_EMIT mainWindow_->ActiveMapMoved(latitude, longitude);
}
},
Qt::QueuedConnection);
connect(mapWidget,
&map::MapWidget::MapStyleChanged,
this,
[&](const std::string& mapStyle)
{
if (mapWidget == activeMap_)
{
UpdateMapStyle(mapStyle);
}
});
connect(
mapWidget,
&map::MapWidget::MouseCoordinateChanged,
this,
[this](common::Coordinate coordinate)
{
const QString latitude = QString::fromStdString(
common::GetLatitudeString(coordinate.latitude_));
const QString longitude = QString::fromStdString(
common::GetLongitudeString(coordinate.longitude_));
coordinateLabel_->setText(
QString("%1, %2").arg(latitude).arg(longitude));
coordinateLabel_->setVisible(true);
for (auto& map : maps_)
{
map->UpdateMouseCoordinate(coordinate);
}
},
Qt::QueuedConnection);
connect(
mapWidget,
&map::MapWidget::RadarSweepUpdated,
this,
[&]()
{
if (mapWidget == activeMap_)
{
UpdateRadarProductSelection(mapWidget->GetRadarProductGroup(),
mapWidget->GetRadarProductName());
UpdateRadarProductSettings();
UpdateRadarSite();
UpdateVcp();
}
},
Qt::QueuedConnection);
connect(
mapWidget,
&map::MapWidget::Level3ProductsChanged,
this,
[&]()
{
if (mapWidget == activeMap_)
{
UpdateAvailableLevel3Products();
}
},
Qt::QueuedConnection);
connect(
mapWidget,
&map::MapWidget::IncomingLevel2ElevationChanged,
this,
[this](std::optional<float>)
{ level2SettingsWidget_->UpdateSettings(activeMap_); },
Qt::QueuedConnection);
}
}
void MainWindowImpl::ConnectAnimationSignals()
{
defaultTimeZoneConnection_ = settings::GeneralSettings::Instance()
.default_time_zone()
.changed_signal()
.connect(
[this]()
{
animationDockWidget_->UpdateTimeZone(
activeMap_->GetDefaultTimeZone());
});
connect(animationDockWidget_,
&ui::AnimationDockWidget::DateTimeChanged,
timelineManager_.get(),
&manager::TimelineManager::SetDateTime);
connect(animationDockWidget_,
&ui::AnimationDockWidget::ViewTypeChanged,
timelineManager_.get(),
&manager::TimelineManager::SetViewType);
connect(animationDockWidget_,
&ui::AnimationDockWidget::LoopTimeChanged,
timelineManager_.get(),
&manager::TimelineManager::SetLoopTime);
connect(animationDockWidget_,
&ui::AnimationDockWidget::LoopSpeedChanged,
timelineManager_.get(),
&manager::TimelineManager::SetLoopSpeed);
connect(animationDockWidget_,
&ui::AnimationDockWidget::LoopDelayChanged,
timelineManager_.get(),
&manager::TimelineManager::SetLoopDelay);
connect(animationDockWidget_,
&ui::AnimationDockWidget::AnimationStepBeginSelected,
timelineManager_.get(),
&manager::TimelineManager::AnimationStepBegin);
connect(animationDockWidget_,
&ui::AnimationDockWidget::AnimationStepBackSelected,
timelineManager_.get(),
&manager::TimelineManager::AnimationStepBack);
connect(animationDockWidget_,
&ui::AnimationDockWidget::AnimationPlaySelected,
timelineManager_.get(),
&manager::TimelineManager::AnimationPlayPause);
connect(animationDockWidget_,
&ui::AnimationDockWidget::AnimationStepNextSelected,
timelineManager_.get(),
&manager::TimelineManager::AnimationStepNext);
connect(animationDockWidget_,
&ui::AnimationDockWidget::AnimationStepEndSelected,
timelineManager_.get(),
&manager::TimelineManager::AnimationStepEnd);
connect(timelineManager_.get(),
&manager::TimelineManager::SelectedTimeUpdated,
[this](std::chrono::system_clock::time_point dateTime)
{
selectedTime_ = dateTime;
for (auto map : maps_)
{
map->SelectTime(dateTime);
textEventManager_->SelectTime(dateTime);
QMetaObject::invokeMethod(
map, static_cast<void (QWidget::*)()>(&QWidget::update));
}
});
connect(timelineManager_.get(),
&manager::TimelineManager::AnimationStateUpdated,
animationDockWidget_,
&ui::AnimationDockWidget::UpdateAnimationState);
connect(timelineManager_.get(),
&manager::TimelineManager::ViewTypeUpdated,
animationDockWidget_,
&ui::AnimationDockWidget::UpdateViewType);
connect(timelineManager_.get(),
&manager::TimelineManager::LiveStateUpdated,
animationDockWidget_,
&ui::AnimationDockWidget::UpdateLiveState);
connect(timelineManager_.get(),
&manager::TimelineManager::LiveStateUpdated,
[this](bool isLive)
{
for (auto map : maps_)
{
map->SetAutoUpdate(isLive);
}
});
for (std::size_t i = 0; i < maps_.size(); i++)
{
connect(maps_[i],
&map::MapWidget::RadarSweepUpdated,
timelineManager_.get(),
[=, this]() { timelineManager_->ReceiveRadarSweepUpdated(i); });
connect(maps_[i],
&map::MapWidget::RadarSweepNotUpdated,
timelineManager_.get(),
[=, this](types::NoUpdateReason reason)
{ timelineManager_->ReceiveRadarSweepNotUpdated(i, reason); });
connect(maps_[i],
&map::MapWidget::WidgetPainted,
timelineManager_.get(),
[=, this]() { timelineManager_->ReceiveMapWidgetPainted(i); });
connect(maps_[i],
&map::MapWidget::RadarSiteRequested,
this,
[this](const std::string& id, bool updateCoordinates)
{
for (map::MapWidget* map : maps_)
{
map->SelectRadarSite(id, updateCoordinates);
}
UpdateRadarSite();
});
}
}
void MainWindowImpl::ConnectOtherSignals()
{
connect(qApp,
&QApplication::focusChanged,
mainWindow_,
[this](QWidget* /*old*/, QWidget* now) { HandleFocusChange(now); });
connect(mainWindow_->ui->mapStyleComboBox,
&QComboBox::currentTextChanged,
mainWindow_,
[&](const QString& text)
{
activeMap_->SetMapStyle(text.toStdString());
// Update settings for active map
for (std::size_t i = 0; i < maps_.size(); ++i)
{
if (maps_[i] == activeMap_)
{
auto& mapSettings = settings::MapSettings::Instance();
mapSettings.map_style(i).StageValue(text.toStdString());
break;
}
}
});
connect(
mainWindow_->ui->smoothRadarDataCheckBox,
&QCheckBox::checkStateChanged,
mainWindow_,
[this](Qt::CheckState state)
{
const bool smoothingEnabled = (state == Qt::CheckState::Checked);
auto it = std::find(maps_.cbegin(), maps_.cend(), activeMap_);
if (it != maps_.cend())
{
const std::size_t i = std::distance(maps_.cbegin(), it);
settings::MapSettings::Instance().smoothing_enabled(i).StageValue(
smoothingEnabled);
}
// Turn on smoothing
activeMap_->SetSmoothingEnabled(smoothingEnabled);
});
connect(mainWindow_->ui->trackLocationCheckBox,
&QCheckBox::checkStateChanged,
mainWindow_,
[this](Qt::CheckState state)
{
bool trackingEnabled = (state == Qt::CheckState::Checked);
settings::GeneralSettings::Instance().track_location().StageValue(
trackingEnabled);
// Turn on location tracking
positionManager_->TrackLocation(trackingEnabled);
});
connect(
mainWindow_->ui->saveRadarProductsButton,
&QAbstractButton::clicked,
mainWindow_,
[this]()
{
auto& mapSettings = settings::MapSettings::Instance();
for (std::size_t i = 0; i < maps_.size(); i++)
{
const auto& map = maps_.at(i);
mapSettings.radar_product_group(i).StageValue(
common::GetRadarProductGroupName(map->GetRadarProductGroup()));
mapSettings.radar_product(i).StageValue(map->GetRadarProductName());
}
});
connect(
level2ProductsWidget_,
&ui::Level2ProductsWidget::RadarProductSelected,
mainWindow_,
[&](common::RadarProductGroup group,
const std::string& productName,
int16_t productCode)
{ SelectRadarProduct(activeMap_, group, productName, productCode); });
connect(
level3ProductsWidget_,
&ui::Level3ProductsWidget::RadarProductSelected,
mainWindow_,
[&](common::RadarProductGroup group,
const std::string& productName,
int16_t productCode)
{ SelectRadarProduct(activeMap_, group, productName, productCode); });
connect(level2SettingsWidget_,
&ui::Level2SettingsWidget::ElevationSelected,
mainWindow_,
[&](float elevation) { SelectElevation(activeMap_, elevation); });
connect(mainWindow_,
&MainWindow::ActiveMapMoved,
alertDockWidget_,
&ui::AlertDockWidget::HandleMapUpdate,
Qt::QueuedConnection);
connect(
alertDockWidget_,
&ui::AlertDockWidget::MoveMap,
this,
[this](double latitude, double longitude)
{
for (map::MapWidget* map : maps_)
{
map->SetMapLocation(latitude, longitude, true);
}
UpdateRadarSite();
},
Qt::QueuedConnection);
connect(mainWindow_,
&MainWindow::ActiveMapMoved,
radarSiteDialog_,
&ui::RadarSiteDialog::HandleMapUpdate);
connect(layerModel_.get(),
&model::LayerModel::LayerDisplayChanged,
this,
[this](types::LayerInfo layer)
{
// Find matching layer action
auto it =
std::find_if(layerActions_.begin(),
layerActions_.end(),
[&](const auto& layerAction)
{
const auto& [type, description, action] =
layerAction;
return layer.type_ == type &&
layer.description_ == description;
});
// If matching layer action was found
if (it != layerActions_.end())
{
// Check the action if the layer is displayed on any map
bool anyDisplayed = std::find(layer.displayed_.begin(),
layer.displayed_.end(),
true) != layer.displayed_.end();
auto& action = std::get<2>(*it);
action->setChecked(anyDisplayed);
}
});
connect(layerModel_.get(),
&QAbstractItemModel::modelReset,
this,
[this]() { InitializeLayerDisplayActions(); });
connect(radarSiteDialog_,
&ui::RadarSiteDialog::accepted,
this,
[&]()
{
std::string selectedRadarSite = radarSiteDialog_->radar_site();
for (map::MapWidget* map : maps_)
{
map->SelectRadarSite(selectedRadarSite);
}
UpdateRadarSite();
});
connect(radarSiteModel_.get(),
&model::RadarSiteModel::PresetToggled,
[this](const std::string& siteId, bool isPreset)
{
if (isPreset && !radarSitePresetsActions_.contains(siteId))
{
AddRadarSitePreset(siteId);
}
else if (!isPreset)
{
auto entry = radarSitePresetsActions_.find(siteId);
if (entry != radarSitePresetsActions_.cend())
{
radarSitePresetsMenu_->removeAction(entry->second.get());
radarSitePresetsActions_.erase(entry);
}
}
mainWindow_->ui->radarSitePresetsButton->setVisible(
!radarSitePresetsActions_.empty());
});
connect(updateManager_.get(),
&manager::UpdateManager::UpdateAvailable,
this,
[this](const std::string& latestVersion,
const types::gh::Release& latestRelease)
{
updateDialog_->UpdateReleaseInfo(latestVersion, latestRelease);
updateDialog_->show();
});
connect(&clockTimer_,
&QTimer::timeout,
this,
[this]()
{
timeLabel_->setText(
QString::fromStdString(util::TimeString(util::time::now())));
timeLabel_->setVisible(true);
});
clockTimer_.start(1000);
auto& generalSettings = settings::GeneralSettings::Instance();
homeRadarConnection_ =
generalSettings.default_radar_site().changed_signal().connect(
[this]()
{
const std::shared_ptr<config::RadarSite> radarSite =
activeMap_->GetRadarSite();
const std::string homeRadarSite =
settings::GeneralSettings::Instance()
.default_radar_site()
.GetValue();
if (radarSite == nullptr)
{
mainWindow_->ui->saveRadarProductsButton->setVisible(false);
}
else
{
mainWindow_->ui->saveRadarProductsButton->setVisible(
radarSite->id() == homeRadarSite);
}
});
}
void MainWindowImpl::InitializeLayerDisplayActions()
{
if (!layerActionsInitialized_)
{
layerActions_.emplace(types::LayerType::Information,
types::InformationLayer::ColorTable,
mainWindow_->ui->actionColorTable);
layerActions_.emplace(types::LayerType::Information,
types::InformationLayer::RadarSite,
mainWindow_->ui->actionRadarSites);
layerActions_.emplace(types::LayerType::Data,
types::DataLayer::RadarRange,
mainWindow_->ui->actionRadarRange);
layerActionsInitialized_ = true;
}
for (auto& layerAction : layerActions_)
{
auto& [type, description, action] = layerAction;
types::LayerInfo layer = layerModel_->GetLayerInfo(type, description);
bool anyDisplayed =
std::find(layer.displayed_.begin(), layer.displayed_.end(), true) !=
layer.displayed_.end();
action->setChecked(anyDisplayed);
}
}
void MainWindowImpl::AddRadarSitePreset(const std::string& siteId)
{
auto radarSite = config::RadarSite::Get(siteId);
std::string actionText =
fmt::format("{}: {}", siteId, radarSite->location_name());
auto pair = radarSitePresetsActions_.emplace(
siteId, std::make_shared<QAction>(QString::fromStdString(actionText)));
auto& action = pair.first->second;
QAction* before = nullptr;
// If the radar site is not at the end
if (pair.first != std::prev(radarSitePresetsActions_.cend()))
{
// Insert before the next entry in the list
before = std::next(pair.first)->second.get();
}
radarSitePresetsMenu_->insertAction(before, action.get());
connect(action.get(),
&QAction::triggered,
[this, siteId]()
{
for (map::MapWidget* map : maps_)
{
map->SelectRadarSite(siteId);
}
UpdateRadarSite();
});
}
void MainWindowImpl::HandleFocusChange(QWidget* focused)
{
map::MapWidget* mapWidget = dynamic_cast<map::MapWidget*>(focused);
if (mapWidget != nullptr)
{
SetActiveMap(mapWidget);
UpdateAvailableLevel3Products();
UpdateMapStyle(mapWidget->GetMapStyle());
UpdateRadarProductSelection(mapWidget->GetRadarProductGroup(),
mapWidget->GetRadarProductName());
UpdateRadarProductSettings();
UpdateRadarSite();
UpdateVcp();
}
}
void MainWindowImpl::PopulateCustomMapStyle()
{
auto& generalSettings = settings::GeneralSettings::Instance();
auto customStyleUrl = generalSettings.custom_style_url().GetValue();
auto customStyleDrawLayer =
generalSettings.custom_style_draw_layer().GetValue();
bool newCustomStyleAvailable =
!customStyleUrl.empty() && !customStyleDrawLayer.empty();
if (newCustomStyleAvailable != customStyleAvailable_)
{
static const QString kCustom {"Custom"};
if (newCustomStyleAvailable)
{
mainWindow_->ui->mapStyleComboBox->addItem(kCustom);
}
else
{
int index = mainWindow_->ui->mapStyleComboBox->findText(kCustom);
mainWindow_->ui->mapStyleComboBox->removeItem(index);
}
customStyleAvailable_ = newCustomStyleAvailable;
}
}
void MainWindowImpl::PopulateMapStyles()
{
const auto& mapProviderInfo = map::GetMapProviderInfo(mapProvider_);
for (const auto& mapStyle : mapProviderInfo.mapStyles_)
{
mainWindow_->ui->mapStyleComboBox->addItem(
QString::fromStdString(mapStyle.name_));
}
auto& generalSettings = settings::GeneralSettings::Instance();
auto& customStyleUrl = generalSettings.custom_style_url();
auto& customStyleDrawLayer = generalSettings.custom_style_draw_layer();
customStyleUrlChangedCallbackUuid_ =
customStyleUrl.RegisterValueChangedCallback(
[this]([[maybe_unused]] const std::string& value)
{ PopulateCustomMapStyle(); });
customStyleDrawLayerChangedCallbackUuid_ =
customStyleDrawLayer.RegisterValueChangedCallback(
[this]([[maybe_unused]] const std::string& value)
{ PopulateCustomMapStyle(); });
PopulateCustomMapStyle();
}
void MainWindowImpl::SelectElevation(map::MapWidget* mapWidget, float elevation)
{
if (mapWidget == activeMap_)
{
UpdateElevationSelection(elevation);
}
mapWidget->SelectElevation(elevation);
}
void MainWindowImpl::SelectRadarProduct(map::MapWidget* mapWidget,
common::RadarProductGroup group,
const std::string& productName,
int16_t productCode)
{
logger_->debug("Selecting radar product: {}, {}",
common::GetRadarProductGroupName(group),
productName);
if (mapWidget == activeMap_)
{
UpdateRadarProductSelection(group, productName);
UpdateRadarProductSettings();
}
mapWidget->SelectRadarProduct(
group, productName, productCode, selectedTime_);
}
void MainWindowImpl::SetActiveMap(map::MapWidget* mapWidget)
{
if (mapWidget == activeMap_)
{
return;
}
activeMap_ = mapWidget;
for (map::MapWidget* widget : maps_)
{
widget->SetActive(mapWidget == widget);
}
}
void MainWindowImpl::UpdateAvailableLevel3Products()
{
level3ProductsWidget_->UpdateAvailableProducts(
activeMap_->GetAvailableLevel3Categories());
}
void MainWindowImpl::UpdateElevationSelection(float elevation)
{
level2SettingsWidget_->UpdateElevationSelection(elevation);
}
void MainWindowImpl::UpdateMapParameters(
double latitude, double longitude, double zoom, double bearing, double pitch)
{
for (map::MapWidget* map : maps_)
{
map->SetMapParameters(latitude, longitude, zoom, bearing, pitch);
}
}
void MainWindowImpl::UpdateMapStyle(const std::string& styleName)
{
int index = mainWindow_->ui->mapStyleComboBox->findText(
QString::fromStdString(styleName));
if (index != -1)
{
mainWindow_->ui->mapStyleComboBox->setCurrentIndex(index);
// Update settings for active map
for (std::size_t i = 0; i < maps_.size(); ++i)
{
if (maps_[i] == activeMap_)
{
auto& mapSettings = settings::MapSettings::Instance();
mapSettings.map_style(i).StageValue(styleName);
break;
}
}
}
}
void MainWindowImpl::UpdateRadarProductSelection(
common::RadarProductGroup group, const std::string& product)
{
level2ProductsWidget_->UpdateProductSelection(group, product);
level3ProductsWidget_->UpdateProductSelection(group, product);
}
void MainWindowImpl::UpdateRadarProductSettings()
{
if (activeMap_->GetRadarProductGroup() == common::RadarProductGroup::Level2)
{
level2SettingsGroup_->setVisible(true);
// This should be done after setting visible for correct sizing
level2SettingsWidget_->UpdateSettings(activeMap_);
}
else
{
level2SettingsGroup_->setVisible(false);
}
mainWindow_->ui->smoothRadarDataCheckBox->setCheckState(
activeMap_->GetSmoothingEnabled() ? Qt::CheckState::Checked :
Qt::CheckState::Unchecked);
mainWindow_->ui->actionRadarWireframe->setChecked(
activeMap_->GetRadarWireframeEnabled());
}
void MainWindowImpl::UpdateRadarSite()
{
std::shared_ptr<config::RadarSite> radarSite = activeMap_->GetRadarSite();
const std::string homeRadarSite =
settings::GeneralSettings::Instance().default_radar_site().GetValue();
if (radarSite != nullptr)
{
mainWindow_->setWindowTitle(
tr("Supercell Wx - %1").arg(QString::fromStdString(radarSite->id())));
mainWindow_->ui->radarSiteValueLabel->setVisible(true);
mainWindow_->ui->radarLocationLabel->setVisible(true);
mainWindow_->ui->radarSiteValueLabel->setText(radarSite->id().c_str());
mainWindow_->ui->radarLocationLabel->setText(
radarSite->location_name().c_str());
timelineManager_->SetRadarSite(radarSite->id());
mainWindow_->ui->saveRadarProductsButton->setVisible(radarSite->id() ==
homeRadarSite);
}
else
{
mainWindow_->setWindowTitle(tr("Supercell Wx"));
mainWindow_->ui->radarSiteValueLabel->setVisible(false);
mainWindow_->ui->radarLocationLabel->setVisible(false);
mainWindow_->ui->saveRadarProductsButton->setVisible(false);
timelineManager_->SetRadarSite("?");
}
alertManager_->SetRadarSite(radarSite);
placefileManager_->SetRadarSite(radarSite);
animationDockWidget_->UpdateTimeZone(activeMap_->GetDefaultTimeZone());
}
void MainWindowImpl::UpdateVcp()
{
uint16_t vcp = activeMap_->GetVcp();
if (vcp != 0)
{
mainWindow_->ui->vcpLabel->setVisible(true);
mainWindow_->ui->vcpValueLabel->setVisible(true);
mainWindow_->ui->vcpDescriptionLabel->setVisible(true);
mainWindow_->ui->vcpValueLabel->setText(QString::number(vcp));
mainWindow_->ui->vcpDescriptionLabel->setText(
tr(common::GetVcpDescription(vcp).c_str()));
}
else
{
mainWindow_->ui->vcpLabel->setVisible(false);
mainWindow_->ui->vcpValueLabel->setVisible(false);
mainWindow_->ui->vcpDescriptionLabel->setVisible(false);
}
}
} // namespace main
} // namespace qt
} // namespace scwx
#include "main_window.moc"