mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 21:00:05 +00:00 
			
		
		
		
	Initial alert model
This commit is contained in:
		
							parent
							
								
									5cf9746e97
								
							
						
					
					
						commit
						9afba385ea
					
				
					 3 changed files with 286 additions and 2 deletions
				
			
		|  | @ -84,11 +84,13 @@ set(SRC_MAP source/scwx/qt/map/color_table_layer.cpp | ||||||
|             source/scwx/qt/map/overlay_layer.cpp |             source/scwx/qt/map/overlay_layer.cpp | ||||||
|             source/scwx/qt/map/radar_product_layer.cpp |             source/scwx/qt/map/radar_product_layer.cpp | ||||||
|             source/scwx/qt/map/radar_range_layer.cpp) |             source/scwx/qt/map/radar_range_layer.cpp) | ||||||
| set(HDR_MODEL source/scwx/qt/model/radar_product_model.hpp | set(HDR_MODEL source/scwx/qt/model/alert_model.hpp | ||||||
|  |               source/scwx/qt/model/radar_product_model.hpp | ||||||
|               source/scwx/qt/model/radar_site_model.hpp |               source/scwx/qt/model/radar_site_model.hpp | ||||||
|               source/scwx/qt/model/tree_item.hpp |               source/scwx/qt/model/tree_item.hpp | ||||||
|               source/scwx/qt/model/tree_model.hpp) |               source/scwx/qt/model/tree_model.hpp) | ||||||
| set(SRC_MODEL source/scwx/qt/model/radar_product_model.cpp | set(SRC_MODEL source/scwx/qt/model/alert_model.cpp | ||||||
|  |               source/scwx/qt/model/radar_product_model.cpp | ||||||
|               source/scwx/qt/model/radar_site_model.cpp |               source/scwx/qt/model/radar_site_model.cpp | ||||||
|               source/scwx/qt/model/tree_item.cpp |               source/scwx/qt/model/tree_item.cpp | ||||||
|               source/scwx/qt/model/tree_model.cpp) |               source/scwx/qt/model/tree_model.cpp) | ||||||
|  |  | ||||||
							
								
								
									
										237
									
								
								scwx-qt/source/scwx/qt/model/alert_model.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										237
									
								
								scwx-qt/source/scwx/qt/model/alert_model.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,237 @@ | ||||||
|  | #include <scwx/qt/model/alert_model.hpp> | ||||||
|  | #include <scwx/qt/common/types.hpp> | ||||||
|  | #include <scwx/common/geographic.hpp> | ||||||
|  | #include <scwx/util/logger.hpp> | ||||||
|  | 
 | ||||||
|  | #include <format> | ||||||
|  | 
 | ||||||
|  | #include <GeographicLib/Geodesic.hpp> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace model | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | static const std::string logPrefix_ = "scwx::qt::model::alert_model"; | ||||||
|  | static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | ||||||
|  | 
 | ||||||
|  | static constexpr size_t kColumnEtn          = 0u; | ||||||
|  | static constexpr size_t kColumnOfficeId     = 1u; | ||||||
|  | static constexpr size_t kColumnPhenomenon   = 2u; | ||||||
|  | static constexpr size_t kColumnSignificance = 3u; | ||||||
|  | static constexpr size_t kColumnState        = 4u; | ||||||
|  | static constexpr size_t kColumnCounties     = 5u; | ||||||
|  | static constexpr size_t kColumnStartTime    = 6u; | ||||||
|  | static constexpr size_t kColumnEndTime      = 7u; | ||||||
|  | static constexpr size_t kColumnDistance     = 8u; | ||||||
|  | static constexpr size_t kFirstColumn        = kColumnEtn; | ||||||
|  | static constexpr size_t kLastColumn         = kColumnDistance; | ||||||
|  | static constexpr size_t kNumColumns         = 9u; | ||||||
|  | 
 | ||||||
|  | class AlertModelImpl | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    explicit AlertModelImpl(); | ||||||
|  |    ~AlertModelImpl() = default; | ||||||
|  | 
 | ||||||
|  |    QList<types::TextEventKey> textEventKeys_; | ||||||
|  | 
 | ||||||
|  |    GeographicLib::Geodesic geodesic_; | ||||||
|  | 
 | ||||||
|  |    std::unordered_map<types::TextEventKey, | ||||||
|  |                       double, | ||||||
|  |                       types::TextEventHash<types::TextEventKey>> | ||||||
|  |                               distanceMap_; | ||||||
|  |    scwx::common::DistanceType distanceDisplay_; | ||||||
|  |    scwx::common::Coordinate   previousPosition_; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | AlertModel::AlertModel(QObject* parent) : | ||||||
|  |     QAbstractTableModel(parent), p(std::make_unique<AlertModelImpl>()) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | AlertModel::~AlertModel() = default; | ||||||
|  | 
 | ||||||
|  | int AlertModel::rowCount(const QModelIndex& parent) const | ||||||
|  | { | ||||||
|  |    return parent.isValid() ? 0 : p->textEventKeys_.size(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int AlertModel::columnCount(const QModelIndex& parent) const | ||||||
|  | { | ||||||
|  |    return parent.isValid() ? 0 : static_cast<int>(kNumColumns); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | QVariant AlertModel::data(const QModelIndex& index, int role) const | ||||||
|  | { | ||||||
|  |    if (index.isValid() && index.row() >= 0 && | ||||||
|  |        index.row() < p->textEventKeys_.size() && | ||||||
|  |        (role == Qt::DisplayRole || role == common::SortRole)) | ||||||
|  |    { | ||||||
|  |       const auto& textEventKey = p->textEventKeys_.at(index.row()); | ||||||
|  | 
 | ||||||
|  |       switch (index.column()) | ||||||
|  |       { | ||||||
|  |       case kColumnEtn: | ||||||
|  |          return textEventKey.etn_; | ||||||
|  |       case kColumnOfficeId: | ||||||
|  |          return QString::fromStdString(textEventKey.officeId_); | ||||||
|  |       case kColumnPhenomenon: | ||||||
|  |          return QString::fromStdString( | ||||||
|  |             awips::GetPhenomenonText(textEventKey.phenomenon_)); | ||||||
|  |       case kColumnSignificance: | ||||||
|  |          return QString::fromStdString( | ||||||
|  |             awips::GetSignificanceText(textEventKey.significance_)); | ||||||
|  |       case kColumnState: | ||||||
|  |          return QString::fromStdString("?"); | ||||||
|  |       case kColumnCounties: | ||||||
|  |          return QString::fromStdString("?"); | ||||||
|  |       case kColumnStartTime: | ||||||
|  |          return QString::fromStdString("?"); | ||||||
|  |       case kColumnEndTime: | ||||||
|  |          return QString::fromStdString("?"); | ||||||
|  |       case kColumnDistance: | ||||||
|  |          if (role == Qt::DisplayRole) | ||||||
|  |          { | ||||||
|  |             if (p->distanceDisplay_ == scwx::common::DistanceType::Miles) | ||||||
|  |             { | ||||||
|  |                return QString("%1 mi").arg( | ||||||
|  |                   static_cast<uint32_t>(p->distanceMap_.at(textEventKey) * | ||||||
|  |                                         scwx::common::kMilesPerMeter)); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                return QString("%1 km").arg( | ||||||
|  |                   static_cast<uint32_t>(p->distanceMap_.at(textEventKey) * | ||||||
|  |                                         scwx::common::kKilometersPerMeter)); | ||||||
|  |             } | ||||||
|  |          } | ||||||
|  |          else | ||||||
|  |          { | ||||||
|  |             return p->distanceMap_.at(textEventKey); | ||||||
|  |          } | ||||||
|  |       default: | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return QVariant(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | QVariant | ||||||
|  | AlertModel::headerData(int section, Qt::Orientation orientation, int role) const | ||||||
|  | { | ||||||
|  |    if (role == Qt::DisplayRole) | ||||||
|  |    { | ||||||
|  |       if (orientation == Qt::Horizontal) | ||||||
|  |       { | ||||||
|  |          switch (section) | ||||||
|  |          { | ||||||
|  |          case kColumnEtn: | ||||||
|  |             return tr("ETN"); | ||||||
|  |          case kColumnOfficeId: | ||||||
|  |             return tr("Office ID"); | ||||||
|  |          case kColumnPhenomenon: | ||||||
|  |             return tr("Phenomenon"); | ||||||
|  |          case kColumnSignificance: | ||||||
|  |             return tr("Significance"); | ||||||
|  |          case kColumnState: | ||||||
|  |             return tr("State"); | ||||||
|  |          case kColumnCounties: | ||||||
|  |             return tr("Counties"); | ||||||
|  |          case kColumnStartTime: | ||||||
|  |             return tr("Start Time"); | ||||||
|  |          case kColumnEndTime: | ||||||
|  |             return tr("End Time"); | ||||||
|  |          case kColumnDistance: | ||||||
|  |             return tr("Distance"); | ||||||
|  |          default: | ||||||
|  |             break; | ||||||
|  |          } | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return QVariant(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void AlertModel::HandleAlert(const types::TextEventKey& alertKey) | ||||||
|  | { | ||||||
|  |    logger_->trace("Handle alert: {}, {}, {}, {}", | ||||||
|  |                   alertKey.etn_, | ||||||
|  |                   alertKey.officeId_, | ||||||
|  |                   awips::GetPhenomenonText(alertKey.phenomenon_), | ||||||
|  |                   awips::GetSignificanceText(alertKey.significance_)); | ||||||
|  | 
 | ||||||
|  |    double distanceInMeters; | ||||||
|  | 
 | ||||||
|  |    if (!p->textEventKeys_.contains(alertKey)) | ||||||
|  |    { | ||||||
|  |       beginInsertRows(QModelIndex(), 0, 0); | ||||||
|  | 
 | ||||||
|  |       p->textEventKeys_.push_back(alertKey); | ||||||
|  | 
 | ||||||
|  |       p->geodesic_.Inverse(p->previousPosition_.latitude_, | ||||||
|  |                            p->previousPosition_.longitude_, | ||||||
|  |                            0.0, // TODO: textEvent->latitude(),
 | ||||||
|  |                            0.0, // TODO: textEvent->longitude(),
 | ||||||
|  |                            distanceInMeters); | ||||||
|  | 
 | ||||||
|  |       p->distanceMap_[alertKey] = distanceInMeters; | ||||||
|  | 
 | ||||||
|  |       endInsertRows(); | ||||||
|  |    } | ||||||
|  |    else | ||||||
|  |    { | ||||||
|  |       p->geodesic_.Inverse(p->previousPosition_.latitude_, | ||||||
|  |                            p->previousPosition_.longitude_, | ||||||
|  |                            0.0, // TODO: textEvent->latitude(),
 | ||||||
|  |                            0.0, // TODO: textEvent->longitude(),
 | ||||||
|  |                            distanceInMeters); | ||||||
|  | 
 | ||||||
|  |       const int   row         = 0; // TODO
 | ||||||
|  |       QModelIndex topLeft     = createIndex(row, kFirstColumn); | ||||||
|  |       QModelIndex bottomRight = createIndex(row, kLastColumn); | ||||||
|  | 
 | ||||||
|  |       emit dataChanged(topLeft, bottomRight); | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void AlertModel::HandleMapUpdate(double latitude, double longitude) | ||||||
|  | { | ||||||
|  |    logger_->trace("Handle map update: {}, {}", latitude, longitude); | ||||||
|  | 
 | ||||||
|  |    double distanceInMeters; | ||||||
|  | 
 | ||||||
|  |    for (const auto& textEvent : p->textEventKeys_) | ||||||
|  |    { | ||||||
|  |       p->geodesic_.Inverse(latitude, | ||||||
|  |                            longitude, | ||||||
|  |                            0.0, // TODO: textEvent->latitude(),
 | ||||||
|  |                            0.0, // TODO: textEvent->longitude(),
 | ||||||
|  |                            distanceInMeters); | ||||||
|  |       p->distanceMap_[textEvent] = distanceInMeters; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    p->previousPosition_ = {latitude, longitude}; | ||||||
|  | 
 | ||||||
|  |    QModelIndex topLeft     = createIndex(0, kColumnDistance); | ||||||
|  |    QModelIndex bottomRight = createIndex(rowCount() - 1, kColumnDistance); | ||||||
|  | 
 | ||||||
|  |    emit dataChanged(topLeft, bottomRight); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | AlertModelImpl::AlertModelImpl() : | ||||||
|  |     textEventKeys_ {}, | ||||||
|  |     geodesic_(GeographicLib::Constants::WGS84_a(), | ||||||
|  |               GeographicLib::Constants::WGS84_f()), | ||||||
|  |     distanceMap_ {}, | ||||||
|  |     distanceDisplay_ {scwx::common::DistanceType::Miles}, | ||||||
|  |     previousPosition_ {} | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace model
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
							
								
								
									
										45
									
								
								scwx-qt/source/scwx/qt/model/alert_model.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								scwx-qt/source/scwx/qt/model/alert_model.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,45 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <scwx/qt/types/text_event_key.hpp> | ||||||
|  | 
 | ||||||
|  | #include <memory> | ||||||
|  | 
 | ||||||
|  | #include <QAbstractTableModel> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace model | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | class AlertModelImpl; | ||||||
|  | 
 | ||||||
|  | class AlertModel : public QAbstractTableModel | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    explicit AlertModel(QObject* parent = nullptr); | ||||||
|  |    ~AlertModel(); | ||||||
|  | 
 | ||||||
|  |    int rowCount(const QModelIndex& parent = QModelIndex()) const override; | ||||||
|  |    int columnCount(const QModelIndex& parent = QModelIndex()) const override; | ||||||
|  | 
 | ||||||
|  |    QVariant data(const QModelIndex& index, | ||||||
|  |                  int                role = Qt::DisplayRole) const override; | ||||||
|  |    QVariant headerData(int             section, | ||||||
|  |                        Qt::Orientation orientation, | ||||||
|  |                        int             role = Qt::DisplayRole) const override; | ||||||
|  | 
 | ||||||
|  | public slots: | ||||||
|  |    void HandleAlert(const types::TextEventKey& alertKey); | ||||||
|  |    void HandleMapUpdate(double latitude, double longitude); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |    std::unique_ptr<AlertModelImpl> p; | ||||||
|  | 
 | ||||||
|  |    friend class AlertModelImpl; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace model
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat