#include "main_window.hpp" #include "./ui_main_window.h" #include #include #include #include #include #include #include #include namespace scwx { namespace qt { namespace main { static const std::string logPrefix_ = "[scwx::qt::main::main_window] "; class MainWindowImpl : public QObject { Q_OBJECT public: explicit MainWindowImpl(MainWindow* mainWindow) : mainWindow_ {mainWindow}, settings_ {}, activeMap_ {nullptr}, maps_ {}, elevationCuts_ {}, resizeElevationButtons_ {false} { settings_.setCacheDatabasePath("/tmp/mbgl-cache.db"); settings_.setCacheDatabaseMaximumSize(20 * 1024 * 1024); } ~MainWindowImpl() = default; void ConfigureMapLayout(); void HandleFocusChange(QWidget* focused); void InitializeConnections(); void SelectElevation(map::MapWidget* mapWidget, float elevation); void SelectRadarProduct(map::MapWidget* mapWidget, common::Level2Product product); void SetActiveMap(map::MapWidget* mapWidget); void UpdateElevationSelection(float elevation); void UpdateRadarProductSettings(); MainWindow* mainWindow_; QMapboxGLSettings settings_; map::MapWidget* activeMap_; std::vector maps_; std::vector elevationCuts_; bool elevationButtonsChanged_; bool resizeElevationButtons_; public slots: void UpdateMapParameters(double latitude, double longitude, double zoom, double bearing, double pitch); }; MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), p(std::make_unique(this)), ui(new Ui::MainWindow) { ui->setupUi(this); p->ConfigureMapLayout(); // Add Level 2 Products QLayout* level2Layout = new ui::FlowLayout(); level2Layout->setContentsMargins(0, 0, 0, 0); ui->level2ProductFrame->setLayout(level2Layout); for (common::Level2Product product : common::Level2ProductIterator()) { QToolButton* toolButton = new QToolButton(); toolButton->setText( QString::fromStdString(common::GetLevel2Name(product))); toolButton->setStatusTip( tr(common::GetLevel2Description(product).c_str())); level2Layout->addWidget(toolButton); connect(toolButton, &QToolButton::clicked, this, [=]() { p->SelectRadarProduct(p->activeMap_, product); }); } QLayout* elevationLayout = new ui::FlowLayout(); ui->elevationGroupBox->setLayout(elevationLayout); ui->settingsGroupBox->setVisible(false); ui->declutterCheckbox->setVisible(false); p->InitializeConnections(); p->SelectRadarProduct(p->activeMap_, common::Level2Product::Reflectivity); if (p->maps_.at(1) != nullptr) { p->SelectRadarProduct(p->maps_.at(1), common::Level2Product::Velocity); } connect(qApp, &QApplication::focusChanged, this, [=](QWidget* old, QWidget* now) { p->HandleFocusChange(now); }); } MainWindow::~MainWindow() { delete ui; } bool MainWindow::event(QEvent* event) { if (event->type() == QEvent::Type::Paint) { if (p->elevationButtonsChanged_) { p->elevationButtonsChanged_ = false; } else if (p->resizeElevationButtons_) { // Set each elevation cut's tool button to the same size int elevationCutMaxWidth = 0; for (QToolButton* widget : ui->elevationGroupBox->findChildren()) { elevationCutMaxWidth = std::max(elevationCutMaxWidth, widget->width()); } for (QToolButton* widget : ui->elevationGroupBox->findChildren()) { widget->setMinimumWidth(elevationCutMaxWidth); } p->resizeElevationButtons_ = false; } } return QMainWindow::event(event); } void MainWindow::showEvent(QShowEvent* event) { QMainWindow::showEvent(event); // Set each level 2 product's tool button to the same size int level2MaxWidth = 0; for (QToolButton* widget : ui->level2ProductFrame->findChildren()) { level2MaxWidth = std::max(level2MaxWidth, widget->width()); } for (QToolButton* widget : ui->level2ProductFrame->findChildren()) { widget->setMinimumWidth(level2MaxWidth); } // Set each elevation cut's tool button to the same size int elevationCutMaxWidth = 0; for (QToolButton* widget : ui->elevationGroupBox->findChildren()) { elevationCutMaxWidth = std::max(elevationCutMaxWidth, widget->width()); } for (QToolButton* widget : ui->elevationGroupBox->findChildren()) { widget->setMinimumWidth(elevationCutMaxWidth); } resizeDocks({ui->radarToolboxDock}, {150}, Qt::Horizontal); } void MainWindow::on_actionExit_triggered() { close(); } void MainWindowImpl::ConfigureMapLayout() { auto generalSettings = manager::SettingsManager::general_settings(); const int64_t gridWidth = generalSettings->grid_width(); const int64_t gridHeight = generalSettings->grid_height(); const int64_t mapCount = gridWidth * gridHeight; size_t mapIndex = 0; QSplitter* vs = new QSplitter(Qt::Vertical); vs->setHandleWidth(1); maps_.resize(mapCount); auto MoveSplitter = [=](int pos, int index) { QSplitter* s = dynamic_cast(sender()); if (s != nullptr) { auto sizes = s->sizes(); for (QSplitter* hs : vs->findChildren()) { hs->setSizes(sizes); } } }; 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) { maps_[mapIndex] = new map::MapWidget(settings_); connect(maps_[mapIndex], &map::MapWidget::MapParametersChanged, this, &MainWindowImpl::UpdateMapParameters); } hs->addWidget(maps_[mapIndex]); } connect(hs, &QSplitter::splitterMoved, this, MoveSplitter); } mainWindow_->ui->centralwidget->layout()->addWidget(vs); SetActiveMap(maps_.at(0)); } void MainWindowImpl::HandleFocusChange(QWidget* focused) { map::MapWidget* mapWidget = dynamic_cast(focused); if (mapWidget != nullptr) { SetActiveMap(mapWidget); } } void MainWindowImpl::InitializeConnections() { connect( activeMap_, &map::MapWidget::RadarSweepUpdated, this, [this]() { UpdateRadarProductSettings(); }, Qt::QueuedConnection); } void MainWindowImpl::SelectElevation(map::MapWidget* mapWidget, float elevation) { mapWidget->SelectElevation(elevation); if (mapWidget == activeMap_) { UpdateElevationSelection(elevation); } } void MainWindowImpl::SelectRadarProduct(map::MapWidget* mapWidget, common::Level2Product product) { const std::string& productName = common::GetLevel2Name(product); BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Selecting Level 2 radar product: " << productName; if (mapWidget == activeMap_) { for (QToolButton* toolButton : mainWindow_->ui->level2ProductFrame->findChildren()) { if (toolButton->text().toStdString() == productName) { toolButton->setCheckable(true); toolButton->setChecked(true); } else { toolButton->setChecked(false); toolButton->setCheckable(false); } } } mapWidget->SelectRadarProduct(product); } void MainWindowImpl::SetActiveMap(map::MapWidget* mapWidget) { if (mapWidget == activeMap_) { return; } activeMap_ = mapWidget; for (map::MapWidget* widget : maps_) { widget->SetActive(mapWidget == widget); } } void MainWindowImpl::UpdateElevationSelection(float elevation) { QString buttonText {QString::number(elevation, 'f', 1) + common::Characters::DEGREE}; for (QToolButton* toolButton : mainWindow_->ui->elevationGroupBox->findChildren()) { if (toolButton->text() == buttonText) { toolButton->setCheckable(true); toolButton->setChecked(true); } else { toolButton->setChecked(false); toolButton->setCheckable(false); } } } 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::UpdateRadarProductSettings() { float currentElevation = activeMap_->GetElevation(); std::vector elevationCuts = activeMap_->GetElevationCuts(); if (elevationCuts_ != elevationCuts) { for (QToolButton* toolButton : mainWindow_->ui->elevationGroupBox->findChildren()) { delete toolButton; } QLayout* layout = mainWindow_->ui->elevationGroupBox->layout(); // Create elevation cut tool buttons for (float elevationCut : elevationCuts) { QToolButton* toolButton = new QToolButton(); toolButton->setText(QString::number(elevationCut, 'f', 1) + common::Characters::DEGREE); layout->addWidget(toolButton); connect(toolButton, &QToolButton::clicked, this, [=]() { SelectElevation(activeMap_, elevationCut); }); } elevationCuts_ = elevationCuts; elevationButtonsChanged_ = true; resizeElevationButtons_ = true; } UpdateElevationSelection(currentElevation); } } // namespace main } // namespace qt } // namespace scwx #include "main_window.moc"