mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 21:40:05 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			392 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			392 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "main_window.hpp"
 | |
| #include "./ui_main_window.h"
 | |
| 
 | |
| #include <scwx/qt/manager/settings_manager.hpp>
 | |
| #include <scwx/qt/map/map_widget.hpp>
 | |
| #include <scwx/qt/ui/flow_layout.hpp>
 | |
| #include <scwx/common/characters.hpp>
 | |
| #include <scwx/common/products.hpp>
 | |
| 
 | |
| #include <QSplitter>
 | |
| #include <QToolButton>
 | |
| 
 | |
| #include <boost/log/trivial.hpp>
 | |
| 
 | |
| 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<map::MapWidget*> maps_;
 | |
|    std::vector<float>           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<MainWindowImpl>(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<QToolButton*>())
 | |
|          {
 | |
|             elevationCutMaxWidth =
 | |
|                std::max(elevationCutMaxWidth, widget->width());
 | |
|          }
 | |
|          for (QToolButton* widget :
 | |
|               ui->elevationGroupBox->findChildren<QToolButton*>())
 | |
|          {
 | |
|             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<QToolButton*>())
 | |
|    {
 | |
|       level2MaxWidth = std::max(level2MaxWidth, widget->width());
 | |
|    }
 | |
|    for (QToolButton* widget :
 | |
|         ui->level2ProductFrame->findChildren<QToolButton*>())
 | |
|    {
 | |
|       widget->setMinimumWidth(level2MaxWidth);
 | |
|    }
 | |
| 
 | |
|    // Set each elevation cut's tool button to the same size
 | |
|    int elevationCutMaxWidth = 0;
 | |
|    for (QToolButton* widget :
 | |
|         ui->elevationGroupBox->findChildren<QToolButton*>())
 | |
|    {
 | |
|       elevationCutMaxWidth = std::max(elevationCutMaxWidth, widget->width());
 | |
|    }
 | |
|    for (QToolButton* widget :
 | |
|         ui->elevationGroupBox->findChildren<QToolButton*>())
 | |
|    {
 | |
|       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<QSplitter*>(sender());
 | |
| 
 | |
|       if (s != nullptr)
 | |
|       {
 | |
|          auto sizes = s->sizes();
 | |
|          for (QSplitter* hs : vs->findChildren<QSplitter*>())
 | |
|          {
 | |
|             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<map::MapWidget*>(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<QToolButton*>())
 | |
|       {
 | |
|          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<QToolButton*>())
 | |
|    {
 | |
|       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<float> elevationCuts    = activeMap_->GetElevationCuts();
 | |
| 
 | |
|    if (elevationCuts_ != elevationCuts)
 | |
|    {
 | |
|       for (QToolButton* toolButton :
 | |
|            mainWindow_->ui->elevationGroupBox->findChildren<QToolButton*>())
 | |
|       {
 | |
|          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"
 | 
