diff --git a/scwx-qt/source/scwx/qt/main/main_window.cpp b/scwx-qt/source/scwx/qt/main/main_window.cpp index 8e63d88c..61cc1cd6 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.cpp +++ b/scwx-qt/source/scwx/qt/main/main_window.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -187,6 +188,11 @@ public: std::shared_ptr timelineManager_; std::shared_ptr updateManager_; + std::shared_ptr radarSiteModel_ { + model::RadarSiteModel::Instance()}; + std::map> radarSiteFavoriteActions_ {}; + QMenu* radarSiteFavoriteMenu_ {nullptr}; + std::vector maps_; std::vector elevationCuts_; @@ -213,9 +219,14 @@ 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); + ui->radarSiteFavoriteButton->setVisible(false); + + p->radarSiteFavoriteMenu_ = new QMenu(this); + ui->radarSiteFavoriteButton->setMenu(p->radarSiteFavoriteMenu_); // Configure Alert Dock p->alertDockWidget_ = new ui::AlertDockWidget(this); @@ -944,6 +955,58 @@ void MainWindowImpl::ConnectOtherSignals() UpdateRadarSite(); }); + connect( + radarSiteModel_.get(), + &model::RadarSiteModel::FavoriteToggled, + [this](const std::string& siteId, bool isFavorite) + { + if (isFavorite && !radarSiteFavoriteActions_.contains(siteId)) + { + auto radarSite = config::RadarSite::Get(siteId); + std::string actionText = + fmt::format("{}: {}", siteId, radarSite->location_name()); + + auto pair = radarSiteFavoriteActions_.emplace( + siteId, + std::make_shared(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(radarSiteFavoriteActions_.cend())) + { + // Insert before the next entry in the list + before = std::next(pair.first)->second.get(); + } + + radarSiteFavoriteMenu_->insertAction(before, action.get()); + + connect(action.get(), + &QAction::triggered, + [this, siteId]() + { + for (map::MapWidget* map : maps_) + { + map->SelectRadarSite(siteId); + } + + UpdateRadarSite(); + }); + } + else if (!isFavorite) + { + auto entry = radarSiteFavoriteActions_.find(siteId); + if (entry != radarSiteFavoriteActions_.cend()) + { + radarSiteFavoriteMenu_->removeAction(entry->second.get()); + radarSiteFavoriteActions_.erase(entry); + } + } + + mainWindow_->ui->radarSiteFavoriteButton->setVisible( + !radarSiteFavoriteActions_.empty()); + }); connect(updateManager_.get(), &manager::UpdateManager::UpdateAvailable, this, diff --git a/scwx-qt/source/scwx/qt/main/main_window.ui b/scwx-qt/source/scwx/qt/main/main_window.ui index 0ecb6523..2cc0cbed 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.ui +++ b/scwx-qt/source/scwx/qt/main/main_window.ui @@ -141,8 +141,8 @@ 0 0 - 187 - 702 + 193 + 688 @@ -166,28 +166,122 @@ QFrame::Raised - - + + + + + 0 + 0 + + KLSX - + + + + + 0 + 0 + + + + Volume Coverage Pattern + + + VCP + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 16777215 + 13 + + + + ... + + + + :/res/icons/font-awesome-6/house-solid.svg:/res/icons/font-awesome-6/house-solid.svg + + + + + + + + 16777215 + 13 + + + + ... + + + + :/res/icons/font-awesome-6/star-solid.svg:/res/icons/font-awesome-6/star-solid.svg + + + QToolButton::InstantPopup + + + + + + + Radar Site - - - - Volume Coverage Pattern - + + - VCP + St. Louis, MO + + + + + + + 35 + + + + + + + Clear Air Mode @@ -204,44 +298,6 @@ - - - - - 16777215 - 13 - - - - ... - - - - :/res/icons/font-awesome-6/house-solid.svg:/res/icons/font-awesome-6/house-solid.svg - - - - - - - St. Louis, MO - - - - - - - 35 - - - - - - - Clear Air Mode - - - diff --git a/scwx-qt/source/scwx/qt/model/radar_site_model.cpp b/scwx-qt/source/scwx/qt/model/radar_site_model.cpp index 0aed2a31..c5638f2d 100644 --- a/scwx-qt/source/scwx/qt/model/radar_site_model.cpp +++ b/scwx-qt/source/scwx/qt/model/radar_site_model.cpp @@ -224,7 +224,13 @@ void RadarSiteModel::ToggleFavorite(int row) { if (row >= 0 && row < p->favorites_.size()) { - p->favorites_.at(row) = !p->favorites_.at(row); + bool isFavorite = !p->favorites_.at(row); + p->favorites_.at(row) = isFavorite; + + QModelIndex index = createIndex(row, static_cast(Column::Favorite)); + Q_EMIT dataChanged(index, index); + + Q_EMIT FavoriteToggled(p->radarSites_.at(row)->id(), isFavorite); } } @@ -248,6 +254,25 @@ RadarSiteModelImpl::RadarSiteModelImpl() : } } +std::shared_ptr RadarSiteModel::Instance() +{ + static std::weak_ptr radarSiteModelReference_ {}; + static std::mutex instanceMutex_ {}; + + std::unique_lock lock(instanceMutex_); + + std::shared_ptr radarSiteModel = + radarSiteModelReference_.lock(); + + if (radarSiteModel == nullptr) + { + radarSiteModel = std::make_shared(); + radarSiteModelReference_ = radarSiteModel; + } + + return radarSiteModel; +} + } // namespace model } // namespace qt } // namespace scwx diff --git a/scwx-qt/source/scwx/qt/model/radar_site_model.hpp b/scwx-qt/source/scwx/qt/model/radar_site_model.hpp index 7a50f016..22e1deb5 100644 --- a/scwx-qt/source/scwx/qt/model/radar_site_model.hpp +++ b/scwx-qt/source/scwx/qt/model/radar_site_model.hpp @@ -15,6 +15,8 @@ class RadarSiteModelImpl; class RadarSiteModel : public QAbstractTableModel { + Q_OBJECT + public: enum class Column : int { @@ -44,6 +46,11 @@ public: void HandleMapUpdate(double latitude, double longitude); void ToggleFavorite(int row); + static std::shared_ptr Instance(); + +signals: + void FavoriteToggled(const std::string& siteId, bool isFavorite); + private: std::unique_ptr p; diff --git a/scwx-qt/source/scwx/qt/ui/radar_site_dialog.cpp b/scwx-qt/source/scwx/qt/ui/radar_site_dialog.cpp index b35743cc..fff1b0ce 100644 --- a/scwx-qt/source/scwx/qt/ui/radar_site_dialog.cpp +++ b/scwx-qt/source/scwx/qt/ui/radar_site_dialog.cpp @@ -24,13 +24,13 @@ class RadarSiteDialogImpl public: explicit RadarSiteDialogImpl(RadarSiteDialog* self) : self_ {self}, - radarSiteModel_ {new model::RadarSiteModel(self_)}, + radarSiteModel_ {model::RadarSiteModel::Instance()}, proxyModel_ {new QSortFilterProxyModel(self_)}, 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 radarSiteModel_; + scwx::common::Coordinate mapPosition_; bool mapUpdateDeferred_;