mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 20:00:05 +00:00
Merge pull request #108 from dpaulat/feature/radar-presets
Radar Presets
This commit is contained in:
commit
0bec134096
10 changed files with 479 additions and 110 deletions
1
scwx-qt/res/icons/font-awesome-6/house-solid.svg
Normal file
1
scwx-qt/res/icons/font-awesome-6/house-solid.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="18" viewBox="0 0 576 512"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.--><path opacity="1" fill="#000000" d="M575.8 255.5c0 18-15 32.1-32 32.1h-32l.7 160.2c0 2.7-.2 5.4-.5 8.1V472c0 22.1-17.9 40-40 40H456c-1.1 0-2.2 0-3.3-.1c-1.4 .1-2.8 .1-4.2 .1H416 392c-22.1 0-40-17.9-40-40V448 384c0-17.7-14.3-32-32-32H256c-17.7 0-32 14.3-32 32v64 24c0 22.1-17.9 40-40 40H160 128.1c-1.5 0-3-.1-4.5-.2c-1.2 .1-2.4 .2-3.6 .2H104c-22.1 0-40-17.9-40-40V360c0-.9 0-1.9 .1-2.8V287.6H32c-18 0-32-14-32-32.1c0-9 3-17 10-24L266.4 8c7-7 15-8 22-8s15 2 21 7L564.8 231.5c8 7 12 15 11 24z"/></svg>
|
||||
|
After Width: | Height: | Size: 734 B |
1
scwx-qt/res/icons/font-awesome-6/star-solid.svg
Normal file
1
scwx-qt/res/icons/font-awesome-6/star-solid.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="18" viewBox="0 0 576 512"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.--><path opacity="1" fill="#000000" d="M316.9 18C311.6 7 300.4 0 288.1 0s-23.4 7-28.8 18L195 150.3 51.4 171.5c-12 1.8-22 10.2-25.7 21.7s-.7 24.2 7.9 32.7L137.8 329 113.2 474.7c-2 12 3 24.2 12.9 31.3s23 8 33.8 2.3l128.3-68.5 128.3 68.5c10.8 5.7 23.9 4.9 33.8-2.3s14.9-19.3 12.9-31.3L438.5 329 542.7 225.9c8.6-8.5 11.7-21.2 7.9-32.7s-13.7-19.9-25.7-21.7L381.2 150.3 316.9 18z"/></svg>
|
||||
|
After Width: | Height: | Size: 615 B |
|
|
@ -34,6 +34,7 @@
|
|||
<file>res/icons/font-awesome-6/forward-step-solid.svg</file>
|
||||
<file>res/icons/font-awesome-6/gears-solid.svg</file>
|
||||
<file>res/icons/font-awesome-6/github.svg</file>
|
||||
<file>res/icons/font-awesome-6/house-solid.svg</file>
|
||||
<file>res/icons/font-awesome-6/layer-group-solid.svg</file>
|
||||
<file>res/icons/font-awesome-6/palette-solid.svg</file>
|
||||
<file>res/icons/font-awesome-6/pause-solid.svg</file>
|
||||
|
|
@ -44,6 +45,7 @@
|
|||
<file>res/icons/font-awesome-6/square-caret-right-regular.svg</file>
|
||||
<file>res/icons/font-awesome-6/square-minus-regular.svg</file>
|
||||
<file>res/icons/font-awesome-6/square-plus-regular.svg</file>
|
||||
<file>res/icons/font-awesome-6/star-solid.svg</file>
|
||||
<file>res/icons/font-awesome-6/stop-solid.svg</file>
|
||||
<file>res/icons/font-awesome-6/volume-high-solid.svg</file>
|
||||
<file>res/palettes/wct/CC.pal</file>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#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/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>
|
||||
|
|
@ -89,10 +90,7 @@ public:
|
|||
textEventManager_ {manager::TextEventManager::Instance()},
|
||||
timelineManager_ {manager::TimelineManager::Instance()},
|
||||
updateManager_ {manager::UpdateManager::Instance()},
|
||||
maps_ {},
|
||||
elevationCuts_ {},
|
||||
elevationButtonsChanged_ {false},
|
||||
resizeElevationButtons_ {false}
|
||||
maps_ {}
|
||||
{
|
||||
mapProvider_ = map::GetMapProvider(
|
||||
settings::GeneralSettings::Instance().map_provider().GetValue());
|
||||
|
|
@ -129,6 +127,7 @@ public:
|
|||
}
|
||||
~MainWindowImpl() { threadPool_.join(); }
|
||||
|
||||
void AddRadarSitePreset(const std::string& id);
|
||||
void AsyncSetup();
|
||||
void ConfigureMapLayout();
|
||||
void ConfigureMapStyles();
|
||||
|
|
@ -187,14 +186,15 @@ public:
|
|||
std::shared_ptr<manager::TimelineManager> timelineManager_;
|
||||
std::shared_ptr<manager::UpdateManager> updateManager_;
|
||||
|
||||
std::shared_ptr<model::RadarSiteModel> radarSiteModel_ {
|
||||
model::RadarSiteModel::Instance()};
|
||||
std::map<std::string, std::shared_ptr<QAction>> radarSitePresetsActions_ {};
|
||||
QMenu* radarSitePresetsMenu_ {nullptr};
|
||||
|
||||
std::vector<map::MapWidget*> maps_;
|
||||
std::vector<float> elevationCuts_;
|
||||
|
||||
std::chrono::system_clock::time_point volumeTime_ {};
|
||||
|
||||
bool elevationButtonsChanged_;
|
||||
bool resizeElevationButtons_;
|
||||
|
||||
public slots:
|
||||
void UpdateMapParameters(double latitude,
|
||||
double longitude,
|
||||
|
|
@ -213,10 +213,22 @@ MainWindow::MainWindow(QWidget* parent) :
|
|||
// 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);
|
||||
|
||||
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);
|
||||
p->alertDockWidget_->setVisible(false);
|
||||
|
|
@ -521,6 +533,19 @@ 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();
|
||||
|
|
@ -931,6 +956,27 @@ void MainWindowImpl::ConnectOtherSignals()
|
|||
|
||||
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,
|
||||
|
|
@ -942,6 +988,40 @@ void MainWindowImpl::ConnectOtherSignals()
|
|||
});
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ private slots:
|
|||
void on_actionGitHubRepository_triggered();
|
||||
void on_actionCheckForUpdates_triggered();
|
||||
void on_actionAboutSupercellWx_triggered();
|
||||
void on_radarSiteHomeButton_clicked();
|
||||
void on_radarSiteSelectButton_clicked();
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1024</width>
|
||||
<height>22</height>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
|
|
@ -141,8 +141,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>157</width>
|
||||
<height>697</height>
|
||||
<width>193</width>
|
||||
<height>688</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
|
|
@ -166,8 +166,126 @@
|
|||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout" columnstretch="0,1,0">
|
||||
<layout class="QGridLayout" name="gridLayout" columnstretch="0,0,0,0,0,0">
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="radarSiteValueLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">KLSX</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QLabel" name="vcpLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Volume Coverage Pattern</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>VCP</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QToolButton" name="radarSiteHomeButton">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>13</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../scwx-qt.qrc">
|
||||
<normaloff>:/res/icons/font-awesome-6/house-solid.svg</normaloff>:/res/icons/font-awesome-6/house-solid.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="radarSitePresetsButton">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>13</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../scwx-qt.qrc">
|
||||
<normaloff>:/res/icons/font-awesome-6/star-solid.svg</normaloff>:/res/icons/font-awesome-6/star-solid.svg</iconset>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::InstantPopup</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="radarSiteLabel">
|
||||
<property name="text">
|
||||
<string>Radar Site</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="3">
|
||||
<widget class="QLabel" name="radarLocationLabel">
|
||||
<property name="text">
|
||||
<string notr="true">St. Louis, MO</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2" colspan="3">
|
||||
<widget class="QLabel" name="vcpValueLabel">
|
||||
<property name="text">
|
||||
<string notr="true">35</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2" colspan="3">
|
||||
<widget class="QLabel" name="vcpDescriptionLabel">
|
||||
<property name="text">
|
||||
<string>Clear Air Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QToolButton" name="radarSiteSelectButton">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
|
|
@ -180,51 +298,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QLabel" name="radarLocationLabel">
|
||||
<property name="text">
|
||||
<string notr="true">St. Louis, MO</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="vcpLabel">
|
||||
<property name="toolTip">
|
||||
<string>Volume Coverage Pattern</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>VCP</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="radarSiteValueLabel">
|
||||
<property name="text">
|
||||
<string notr="true">KLSX</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="radarSiteLabel">
|
||||
<property name="text">
|
||||
<string>Radar Site</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QLabel" name="vcpDescriptionLabel">
|
||||
<property name="text">
|
||||
<string>Clear Air Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="2">
|
||||
<widget class="QLabel" name="vcpValueLabel">
|
||||
<property name="text">
|
||||
<string notr="true">35</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
|||
|
|
@ -2,9 +2,17 @@
|
|||
#include <scwx/qt/config/radar_site.hpp>
|
||||
#include <scwx/qt/types/qt_types.hpp>
|
||||
#include <scwx/qt/util/geographic_lib.hpp>
|
||||
#include <scwx/qt/util/json.hpp>
|
||||
#include <scwx/common/geographic.hpp>
|
||||
#include <scwx/util/logger.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include <boost/json.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <QIcon>
|
||||
#include <QStandardPaths>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace qt
|
||||
|
|
@ -15,36 +23,138 @@ namespace model
|
|||
static const std::string logPrefix_ = "scwx::qt::model::radar_site_model";
|
||||
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
|
||||
|
||||
static constexpr size_t kColumnSiteId = 0u;
|
||||
static constexpr size_t kColumnPlace = 1u;
|
||||
static constexpr size_t kColumnState = 2u;
|
||||
static constexpr size_t kColumnCountry = 3u;
|
||||
static constexpr size_t kColumnLatitude = 4u;
|
||||
static constexpr size_t kColumnLongitude = 5u;
|
||||
static constexpr size_t kColumnType = 6u;
|
||||
static constexpr size_t kColumnDistance = 7u;
|
||||
static constexpr size_t kNumColumns = 8u;
|
||||
static constexpr int kFirstColumn =
|
||||
static_cast<int>(RadarSiteModel::Column::SiteId);
|
||||
static constexpr int kLastColumn =
|
||||
static_cast<int>(RadarSiteModel::Column::Preset);
|
||||
static constexpr int kNumColumns = kLastColumn - kFirstColumn + 1;
|
||||
|
||||
class RadarSiteModelImpl
|
||||
{
|
||||
public:
|
||||
explicit RadarSiteModelImpl();
|
||||
explicit RadarSiteModelImpl() :
|
||||
radarSites_ {},
|
||||
geodesic_(util::GeographicLib::DefaultGeodesic()),
|
||||
distanceMap_ {},
|
||||
distanceDisplay_ {scwx::common::DistanceType::Miles},
|
||||
previousPosition_ {}
|
||||
{
|
||||
// Get all loaded radar sites
|
||||
std::vector<std::shared_ptr<config::RadarSite>> radarSites =
|
||||
config::RadarSite::GetAll();
|
||||
|
||||
// Setup radar site list
|
||||
for (auto& site : radarSites)
|
||||
{
|
||||
distanceMap_[site->id()] = 0.0;
|
||||
radarSites_.emplace_back(std::move(site));
|
||||
}
|
||||
}
|
||||
~RadarSiteModelImpl() = default;
|
||||
|
||||
void InitializePresets();
|
||||
void ReadPresets();
|
||||
void WritePresets();
|
||||
|
||||
QList<std::shared_ptr<config::RadarSite>> radarSites_;
|
||||
std::unordered_set<std::string> presets_ {};
|
||||
|
||||
std::string presetsPath_ {};
|
||||
|
||||
const GeographicLib::Geodesic& geodesic_;
|
||||
|
||||
std::unordered_map<std::string, double> distanceMap_;
|
||||
scwx::common::DistanceType distanceDisplay_;
|
||||
scwx::common::Coordinate previousPosition_;
|
||||
|
||||
QIcon starIcon_ {":/res/icons/font-awesome-6/star-solid.svg"};
|
||||
};
|
||||
|
||||
RadarSiteModel::RadarSiteModel(QObject* parent) :
|
||||
QAbstractTableModel(parent), p(std::make_unique<RadarSiteModelImpl>())
|
||||
{
|
||||
p->InitializePresets();
|
||||
p->ReadPresets();
|
||||
}
|
||||
|
||||
RadarSiteModel::~RadarSiteModel()
|
||||
{
|
||||
// Write presets on shutdown
|
||||
p->WritePresets();
|
||||
};
|
||||
|
||||
std::unordered_set<std::string> RadarSiteModel::presets() const
|
||||
{
|
||||
return p->presets_;
|
||||
}
|
||||
|
||||
void RadarSiteModelImpl::InitializePresets()
|
||||
{
|
||||
std::string appDataPath {
|
||||
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)
|
||||
.toStdString()};
|
||||
|
||||
if (!std::filesystem::exists(appDataPath))
|
||||
{
|
||||
if (!std::filesystem::create_directories(appDataPath))
|
||||
{
|
||||
logger_->error("Unable to create application data directory: \"{}\"",
|
||||
appDataPath);
|
||||
}
|
||||
}
|
||||
|
||||
presetsPath_ = appDataPath + "/radar-presets.json";
|
||||
}
|
||||
|
||||
void RadarSiteModelImpl::ReadPresets()
|
||||
{
|
||||
logger_->info("Reading presets");
|
||||
|
||||
boost::json::value presetsJson = nullptr;
|
||||
|
||||
// Determine if presets exists
|
||||
if (std::filesystem::exists(presetsPath_))
|
||||
{
|
||||
presetsJson = util::json::ReadJsonFile(presetsPath_);
|
||||
}
|
||||
|
||||
// If presets was successfully read
|
||||
if (presetsJson != nullptr && presetsJson.is_array())
|
||||
{
|
||||
auto& presetsArray = presetsJson.as_array();
|
||||
for (auto& presetsEntry : presetsArray)
|
||||
{
|
||||
if (presetsEntry.is_string())
|
||||
{
|
||||
// Get radar site ID from JSON value
|
||||
std::string preset =
|
||||
boost::json::value_to<std::string>(presetsEntry);
|
||||
boost::to_upper(preset);
|
||||
|
||||
// Find the preset in the list of radar sites
|
||||
auto it = std::find_if(
|
||||
radarSites_.cbegin(),
|
||||
radarSites_.cend(),
|
||||
[&preset](const std::shared_ptr<config::RadarSite>& radarSite)
|
||||
{ return (radarSite->id() == preset); });
|
||||
|
||||
// If a match, add to the presets
|
||||
if (it != radarSites_.cend())
|
||||
{
|
||||
presets_.insert(preset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RadarSiteModelImpl::WritePresets()
|
||||
{
|
||||
logger_->info("Saving presets");
|
||||
|
||||
auto presetsJson = boost::json::value_from(presets_);
|
||||
util::json::WriteJsonFile(presetsPath_, presetsJson);
|
||||
}
|
||||
RadarSiteModel::~RadarSiteModel() = default;
|
||||
|
||||
int RadarSiteModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
|
|
@ -53,28 +163,32 @@ int RadarSiteModel::rowCount(const QModelIndex& parent) const
|
|||
|
||||
int RadarSiteModel::columnCount(const QModelIndex& parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : static_cast<int>(kNumColumns);
|
||||
return parent.isValid() ? 0 : kNumColumns;
|
||||
}
|
||||
|
||||
QVariant RadarSiteModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (index.isValid() && index.row() >= 0 &&
|
||||
index.row() < p->radarSites_.size() &&
|
||||
(role == Qt::DisplayRole || role == types::SortRole))
|
||||
if (!index.isValid() || index.row() < 0 ||
|
||||
index.row() >= p->radarSites_.size())
|
||||
{
|
||||
const auto& site = p->radarSites_.at(index.row());
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const auto& site = p->radarSites_.at(index.row());
|
||||
|
||||
if (role == Qt::DisplayRole || role == types::SortRole)
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case kColumnSiteId:
|
||||
case static_cast<int>(Column::SiteId):
|
||||
return QString::fromStdString(site->id());
|
||||
case kColumnPlace:
|
||||
case static_cast<int>(Column::Place):
|
||||
return QString::fromStdString(site->place());
|
||||
case kColumnState:
|
||||
case static_cast<int>(Column::State):
|
||||
return QString::fromStdString(site->state());
|
||||
case kColumnCountry:
|
||||
case static_cast<int>(Column::Country):
|
||||
return QString::fromStdString(site->country());
|
||||
case kColumnLatitude:
|
||||
case static_cast<int>(Column::Latitude):
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
return QString::fromStdString(
|
||||
|
|
@ -84,7 +198,7 @@ QVariant RadarSiteModel::data(const QModelIndex& index, int role) const
|
|||
{
|
||||
return site->latitude();
|
||||
}
|
||||
case kColumnLongitude:
|
||||
case static_cast<int>(Column::Longitude):
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
return QString::fromStdString(
|
||||
|
|
@ -94,9 +208,9 @@ QVariant RadarSiteModel::data(const QModelIndex& index, int role) const
|
|||
{
|
||||
return site->longitude();
|
||||
}
|
||||
case kColumnType:
|
||||
case static_cast<int>(Column::Type):
|
||||
return QString::fromStdString(site->type_name());
|
||||
case kColumnDistance:
|
||||
case static_cast<int>(Column::Distance):
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (p->distanceDisplay_ == scwx::common::DistanceType::Miles)
|
||||
|
|
@ -116,6 +230,26 @@ QVariant RadarSiteModel::data(const QModelIndex& index, int role) const
|
|||
{
|
||||
return p->distanceMap_.at(site->id());
|
||||
}
|
||||
case static_cast<int>(Column::Preset):
|
||||
if (role == types::SortRole)
|
||||
{
|
||||
return QVariant(p->presets_.contains(site->id()));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (role == Qt::DecorationRole)
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case static_cast<int>(Column::Preset):
|
||||
if (p->presets_.contains(site->id()))
|
||||
{
|
||||
return p->starIcon_;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -134,27 +268,40 @@ QVariant RadarSiteModel::headerData(int section,
|
|||
{
|
||||
switch (section)
|
||||
{
|
||||
case kColumnSiteId:
|
||||
case static_cast<int>(Column::SiteId):
|
||||
return tr("Site ID");
|
||||
case kColumnPlace:
|
||||
case static_cast<int>(Column::Place):
|
||||
return tr("Place");
|
||||
case kColumnState:
|
||||
case static_cast<int>(Column::State):
|
||||
return tr("State");
|
||||
case kColumnCountry:
|
||||
case static_cast<int>(Column::Country):
|
||||
return tr("Country");
|
||||
case kColumnLatitude:
|
||||
case static_cast<int>(Column::Latitude):
|
||||
return tr("Latitude");
|
||||
case kColumnLongitude:
|
||||
case static_cast<int>(Column::Longitude):
|
||||
return tr("Longitude");
|
||||
case kColumnType:
|
||||
case static_cast<int>(Column::Type):
|
||||
return tr("Type");
|
||||
case kColumnDistance:
|
||||
case static_cast<int>(Column::Distance):
|
||||
return tr("Distance");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (role == Qt::DecorationRole)
|
||||
{
|
||||
if (orientation == Qt::Horizontal)
|
||||
{
|
||||
switch (section)
|
||||
{
|
||||
case static_cast<int>(Column::Preset):
|
||||
return p->starIcon_;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
|
@ -175,31 +322,54 @@ void RadarSiteModel::HandleMapUpdate(double latitude, double longitude)
|
|||
p->distanceMap_[site->id()] = distanceInMeters;
|
||||
}
|
||||
|
||||
QModelIndex topLeft = createIndex(0, kColumnDistance);
|
||||
QModelIndex bottomRight = createIndex(rowCount() - 1, kColumnDistance);
|
||||
QModelIndex topLeft = createIndex(0, static_cast<int>(Column::Distance));
|
||||
QModelIndex bottomRight =
|
||||
createIndex(rowCount() - 1, static_cast<int>(Column::Distance));
|
||||
|
||||
Q_EMIT dataChanged(topLeft, bottomRight);
|
||||
}
|
||||
|
||||
RadarSiteModelImpl::RadarSiteModelImpl() :
|
||||
radarSites_ {},
|
||||
geodesic_(util::GeographicLib::DefaultGeodesic()),
|
||||
distanceMap_ {},
|
||||
distanceDisplay_ {scwx::common::DistanceType::Miles},
|
||||
previousPosition_ {}
|
||||
void RadarSiteModel::TogglePreset(int row)
|
||||
{
|
||||
// Get all loaded radar sites
|
||||
std::vector<std::shared_ptr<config::RadarSite>> radarSites =
|
||||
config::RadarSite::GetAll();
|
||||
|
||||
// Setup radar site list
|
||||
for (auto& site : radarSites)
|
||||
if (row >= 0 && row < p->radarSites_.size())
|
||||
{
|
||||
distanceMap_[site->id()] = 0.0;
|
||||
radarSites_.emplace_back(std::move(site));
|
||||
std::string siteId = p->radarSites_.at(row)->id();
|
||||
bool isPreset = false;
|
||||
|
||||
// Attempt to erase the radar site from presets
|
||||
if (p->presets_.erase(siteId) == 0)
|
||||
{
|
||||
// If the radar site did not exist, add it
|
||||
p->presets_.insert(siteId);
|
||||
isPreset = true;
|
||||
}
|
||||
|
||||
QModelIndex index = createIndex(row, static_cast<int>(Column::Preset));
|
||||
Q_EMIT dataChanged(index, index);
|
||||
|
||||
Q_EMIT PresetToggled(siteId, isPreset);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<RadarSiteModel> RadarSiteModel::Instance()
|
||||
{
|
||||
static std::weak_ptr<RadarSiteModel> radarSiteModelReference_ {};
|
||||
static std::mutex instanceMutex_ {};
|
||||
|
||||
std::unique_lock lock(instanceMutex_);
|
||||
|
||||
std::shared_ptr<RadarSiteModel> radarSiteModel =
|
||||
radarSiteModelReference_.lock();
|
||||
|
||||
if (radarSiteModel == nullptr)
|
||||
{
|
||||
radarSiteModel = std::make_shared<RadarSiteModel>();
|
||||
radarSiteModelReference_ = radarSiteModel;
|
||||
}
|
||||
|
||||
return radarSiteModel;
|
||||
}
|
||||
|
||||
} // namespace model
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
|
|
@ -15,10 +16,27 @@ class RadarSiteModelImpl;
|
|||
|
||||
class RadarSiteModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum class Column : int
|
||||
{
|
||||
SiteId = 0,
|
||||
Place = 1,
|
||||
State = 2,
|
||||
Country = 3,
|
||||
Latitude = 4,
|
||||
Longitude = 5,
|
||||
Type = 6,
|
||||
Distance = 7,
|
||||
Preset = 8
|
||||
};
|
||||
|
||||
explicit RadarSiteModel(QObject* parent = nullptr);
|
||||
~RadarSiteModel();
|
||||
|
||||
std::unordered_set<std::string> presets() const;
|
||||
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
|
||||
|
|
@ -29,6 +47,12 @@ public:
|
|||
int role = Qt::DisplayRole) const override;
|
||||
|
||||
void HandleMapUpdate(double latitude, double longitude);
|
||||
void TogglePreset(int row);
|
||||
|
||||
static std::shared_ptr<RadarSiteModel> Instance();
|
||||
|
||||
signals:
|
||||
void PresetToggled(const std::string& siteId, bool isPreset);
|
||||
|
||||
private:
|
||||
std::unique_ptr<RadarSiteModelImpl> p;
|
||||
|
|
|
|||
|
|
@ -24,13 +24,13 @@ class RadarSiteDialogImpl
|
|||
public:
|
||||
explicit RadarSiteDialogImpl(RadarSiteDialog* self) :
|
||||
self_ {self},
|
||||
radarSiteModel_ {new model::RadarSiteModel(self_)},
|
||||
proxyModel_ {new QSortFilterProxyModel(self_)},
|
||||
radarSiteModel_ {model::RadarSiteModel::Instance()},
|
||||
mapPosition_ {},
|
||||
mapUpdateDeferred_ {false},
|
||||
selectedRadarSite_ {"?"}
|
||||
{
|
||||
proxyModel_->setSourceModel(radarSiteModel_);
|
||||
proxyModel_->setSourceModel(radarSiteModel_.get());
|
||||
proxyModel_->setSortRole(types::SortRole);
|
||||
proxyModel_->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
proxyModel_->setFilterKeyColumn(-1);
|
||||
|
|
@ -38,9 +38,10 @@ public:
|
|||
~RadarSiteDialogImpl() = default;
|
||||
|
||||
RadarSiteDialog* self_;
|
||||
model::RadarSiteModel* radarSiteModel_;
|
||||
QSortFilterProxyModel* proxyModel_;
|
||||
|
||||
std::shared_ptr<model::RadarSiteModel> radarSiteModel_;
|
||||
|
||||
scwx::common::Coordinate mapPosition_;
|
||||
bool mapUpdateDeferred_;
|
||||
|
||||
|
|
@ -70,9 +71,22 @@ RadarSiteDialog::RadarSiteDialog(QWidget* parent) :
|
|||
p->proxyModel_,
|
||||
&QSortFilterProxyModel::setFilterWildcard);
|
||||
connect(ui->radarSiteView,
|
||||
&QTreeView::doubleClicked,
|
||||
&QAbstractItemView::doubleClicked,
|
||||
this,
|
||||
[this]() { Q_EMIT accept(); });
|
||||
connect(ui->radarSiteView,
|
||||
&QAbstractItemView::pressed,
|
||||
this,
|
||||
[this](const QModelIndex& index)
|
||||
{
|
||||
QModelIndex selectedIndex = p->proxyModel_->mapToSource(index);
|
||||
|
||||
if (selectedIndex.column() ==
|
||||
static_cast<int>(model::RadarSiteModel::Column::Preset))
|
||||
{
|
||||
p->radarSiteModel_->TogglePreset(selectedIndex.row());
|
||||
}
|
||||
});
|
||||
connect(
|
||||
ui->radarSiteView->selectionModel(),
|
||||
&QItemSelectionModel::selectionChanged,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>576</width>
|
||||
<width>627</width>
|
||||
<height>550</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
|
@ -16,6 +16,9 @@
|
|||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTreeView" name="radarSiteView">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::CurrentChanged|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked</set>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue