Merge pull request #108 from dpaulat/feature/radar-presets

Radar Presets
This commit is contained in:
Dan Paulat 2023-12-20 17:08:08 -06:00 committed by GitHub
commit 0bec134096
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 479 additions and 110 deletions

View 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

View 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

View file

@ -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>

View 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);

View file

@ -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:

View file

@ -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>

View file

@ -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

View file

@ -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;

View file

@ -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,

View file

@ -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>