diff --git a/data b/data index 1d93f410..8eb89b19 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit 1d93f4106761cabbe61e1265bb1d2b8501600177 +Subproject commit 8eb89b19fdd1c78e896cc6cb47e07425bb473699 diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake index 0a3f451f..78d45217 100644 --- a/scwx-qt/scwx-qt.cmake +++ b/scwx-qt/scwx-qt.cmake @@ -240,6 +240,7 @@ set(HDR_UI source/scwx/qt/ui/about_dialog.hpp source/scwx/qt/ui/animation_dock_widget.hpp source/scwx/qt/ui/collapsible_group.hpp source/scwx/qt/ui/county_dialog.hpp + source/scwx/qt/ui/wfo_dialog.hpp source/scwx/qt/ui/download_dialog.hpp source/scwx/qt/ui/flow_layout.hpp source/scwx/qt/ui/gps_info_dialog.hpp @@ -265,6 +266,7 @@ set(SRC_UI source/scwx/qt/ui/about_dialog.cpp source/scwx/qt/ui/animation_dock_widget.cpp source/scwx/qt/ui/collapsible_group.cpp source/scwx/qt/ui/county_dialog.cpp + source/scwx/qt/ui/wfo_dialog.cpp source/scwx/qt/ui/download_dialog.cpp source/scwx/qt/ui/flow_layout.cpp source/scwx/qt/ui/gps_info_dialog.cpp @@ -290,6 +292,7 @@ set(UI_UI source/scwx/qt/ui/about_dialog.ui source/scwx/qt/ui/animation_dock_widget.ui source/scwx/qt/ui/collapsible_group.ui source/scwx/qt/ui/county_dialog.ui + source/scwx/qt/ui/wfo_dialog.ui source/scwx/qt/ui/gps_info_dialog.ui source/scwx/qt/ui/imgui_debug_dialog.ui source/scwx/qt/ui/layer_dialog.ui @@ -388,6 +391,7 @@ set(ZONE_DBF_FILES ${SCWX_DIR}/data/db/fz05mr24.dbf ${SCWX_DIR}/data/db/oz05mr24.dbf ${SCWX_DIR}/data/db/z_05mr24.dbf) set(STATE_DBF_FILES ${SCWX_DIR}/data/db/s_05mr24.dbf) +set(WFO_DBF_FILES ${SCWX_DIR}/data/db/w_05mr24.dbf) set(COUNTIES_SQLITE_DB ${scwx-qt_BINARY_DIR}/res/db/counties.db) set(RESOURCE_INPUT ${scwx-qt_SOURCE_DIR}/res/scwx-qt.rc.in) @@ -483,11 +487,13 @@ add_custom_command(OUTPUT ${COUNTIES_SQLITE_DB} -c ${COUNTY_DBF_FILES} -z ${ZONE_DBF_FILES} -s ${STATE_DBF_FILES} + -w ${WFO_DBF_FILES} -o ${COUNTIES_SQLITE_DB} DEPENDS ${scwx-qt_SOURCE_DIR}/tools/generate_counties_db.py ${COUNTY_DB_FILES} ${STATE_DBF_FILES} - ${ZONE_DBF_FILES}) + ${ZONE_DBF_FILES} + ${WFO_DBF_FILES}) add_custom_target(scwx-qt_generate_counties_db ALL DEPENDS ${COUNTIES_SQLITE_DB}) diff --git a/scwx-qt/source/scwx/qt/config/county_database.cpp b/scwx-qt/source/scwx/qt/config/county_database.cpp index 106b6911..030225ec 100644 --- a/scwx-qt/source/scwx/qt/config/county_database.cpp +++ b/scwx-qt/source/scwx/qt/config/county_database.cpp @@ -31,6 +31,7 @@ typedef std::unordered_map FormatMap; static bool initialized_ {false}; static FormatMap countyDatabase_; static std::unordered_map stateMap_; +static std::unordered_map wfoMap_; void Initialize() { @@ -168,6 +169,39 @@ void Initialize() sqlite3_free(errorMessage); } + // Query database for WFOs + rc = sqlite3_exec( + db, + "SELECT id, city_state FROM wfos", + [](void* /* param */, + int columns, + char** columnText, + char** /* columnName */) -> int + { + int status = 0; + + if (columns == 2) + { + wfoMap_.emplace(columnText[0], columnText[1]); + } + else + { + logger_->error( + "WFO database format error, invalid number of columns: {}", + columns); + status = -1; + } + + return status; + }, + nullptr, + &errorMessage); + if (rc != SQLITE_OK) + { + logger_->error("SQL error: {}", errorMessage); + sqlite3_free(errorMessage); + } + // Close database sqlite3_close(db); @@ -230,6 +264,22 @@ const std::unordered_map& GetStates() return stateMap_; } +const std::unordered_map& GetWFOs() +{ + return wfoMap_; +} + +const std::string& GetWFOName(const std::string& wfoId) +{ + auto wfo = wfoMap_.find(wfoId); + if (wfo == wfoMap_.end()) + { + return wfoId; + } + + return wfo->second; +} + } // namespace CountyDatabase } // namespace config } // namespace qt diff --git a/scwx-qt/source/scwx/qt/config/county_database.hpp b/scwx-qt/source/scwx/qt/config/county_database.hpp index 5ee33e11..e2d427c6 100644 --- a/scwx-qt/source/scwx/qt/config/county_database.hpp +++ b/scwx-qt/source/scwx/qt/config/county_database.hpp @@ -19,6 +19,8 @@ std::string GetCountyName(const std::string& id); std::unordered_map GetCounties(const std::string& state); const std::unordered_map& GetStates(); +const std::unordered_map& GetWFOs(); +const std::string& GetWFOName(const std::string& wfoId); } // namespace CountyDatabase } // namespace config diff --git a/scwx-qt/source/scwx/qt/manager/alert_manager.cpp b/scwx-qt/source/scwx/qt/manager/alert_manager.cpp index 64c78d8d..757754a9 100644 --- a/scwx-qt/source/scwx/qt/manager/alert_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/alert_manager.cpp @@ -151,6 +151,7 @@ void AlertManager::Impl::HandleAlert(const types::TextEventKey& key, std::string alertCounty = audioSettings.alert_county().GetValue(); auto alertRadius = units::length::kilometers( audioSettings.alert_radius().GetValue()); + std::string alertWFO = audioSettings.alert_wfo().GetValue(); auto message = textEventManager_->message_list(key).at(messageIndex); @@ -185,9 +186,7 @@ void AlertManager::Impl::HandleAlert(const types::TextEventKey& key, auto alertCoordinates = segment->codedLocation_->coordinates(); activeAtLocation = util::GeographicLib::AreaInRangeOfPoint( - alertCoordinates, - currentCoordinate, - alertRadius); + alertCoordinates, currentCoordinate, alertRadius); } else if (locationMethod == types::LocationMethod::County) { @@ -196,6 +195,12 @@ void AlertManager::Impl::HandleAlert(const types::TextEventKey& key, auto it = std::find(fipsIds.cbegin(), fipsIds.cend(), alertCounty); activeAtLocation = it != fipsIds.cend(); } + else if (locationMethod == types::LocationMethod::WFO) + { + std::string wfoId = vtec.pVtec_.office_id(); + + activeAtLocation = wfoId == alertWFO; + } if (activeAtLocation) { diff --git a/scwx-qt/source/scwx/qt/settings/audio_settings.cpp b/scwx-qt/source/scwx/qt/settings/audio_settings.cpp index 995ce881..a799793b 100644 --- a/scwx-qt/source/scwx/qt/settings/audio_settings.cpp +++ b/scwx-qt/source/scwx/qt/settings/audio_settings.cpp @@ -39,6 +39,7 @@ public: alertLongitude_.SetDefault(0.0); alertRadius_.SetDefault(0.0); alertRadarSite_.SetDefault("default"); + alertWFO_.SetDefault(""); ignoreMissingCodecs_.SetDefault(false); alertLatitude_.SetMinimum(-90.0); @@ -62,6 +63,14 @@ public: config::CountyDatabase::GetCountyName(value) != value; }); + alertWFO_.SetValidator( + [](const std::string& value) + { + return value.empty() || + config::CountyDatabase::GetWFOs().count(value) != 0; + }); + + auto& alertAudioPhenomena = types::GetAlertAudioPhenomena(); alertEnabled_.reserve(alertAudioPhenomena.size() + 1); @@ -94,6 +103,7 @@ public: SettingsVariable alertRadarSite_ {"alert_radar_site"}; SettingsVariable alertRadius_ {"alert_radius"}; SettingsVariable alertCounty_ {"alert_county"}; + SettingsVariable alertWFO_ {"alert_wfo"}; SettingsVariable ignoreMissingCodecs_ {"ignore_missing_codecs"}; std::unordered_map> @@ -111,6 +121,7 @@ AudioSettings::AudioSettings() : &p->alertRadarSite_, &p->alertRadius_, &p->alertCounty_, + &p->alertWFO_, &p->ignoreMissingCodecs_}); RegisterVariables(p->variables_); SetDefaults(); @@ -157,6 +168,11 @@ SettingsVariable& AudioSettings::alert_county() const return p->alertCounty_; } +SettingsVariable& AudioSettings::alert_wfo() const +{ + return p->alertWFO_; +} + SettingsVariable& AudioSettings::alert_enabled(awips::Phenomenon phenomenon) const { @@ -188,6 +204,7 @@ bool operator==(const AudioSettings& lhs, const AudioSettings& rhs) lhs.p->alertRadarSite_ == rhs.p->alertRadarSite_ && lhs.p->alertRadius_ == rhs.p->alertRadius_ && lhs.p->alertCounty_ == rhs.p->alertCounty_ && + lhs.p->alertWFO_ == rhs.p->alertWFO_ && lhs.p->alertEnabled_ == rhs.p->alertEnabled_); } diff --git a/scwx-qt/source/scwx/qt/settings/audio_settings.hpp b/scwx-qt/source/scwx/qt/settings/audio_settings.hpp index 466c4f3a..579d3599 100644 --- a/scwx-qt/source/scwx/qt/settings/audio_settings.hpp +++ b/scwx-qt/source/scwx/qt/settings/audio_settings.hpp @@ -33,6 +33,7 @@ public: SettingsVariable& alert_radius() const; SettingsVariable& alert_radar_site() const; SettingsVariable& alert_county() const; + SettingsVariable& alert_wfo() const; SettingsVariable& alert_enabled(awips::Phenomenon phenomenon) const; SettingsVariable& ignore_missing_codecs() const; diff --git a/scwx-qt/source/scwx/qt/types/location_types.cpp b/scwx-qt/source/scwx/qt/types/location_types.cpp index f9df0189..228d5718 100644 --- a/scwx-qt/source/scwx/qt/types/location_types.cpp +++ b/scwx-qt/source/scwx/qt/types/location_types.cpp @@ -17,6 +17,7 @@ static const std::unordered_map {LocationMethod::Track, "Track"}, {LocationMethod::RadarSite, "Radar Site"}, {LocationMethod::County, "County"}, + {LocationMethod::WFO, "WFO"}, {LocationMethod::All, "All"}, {LocationMethod::Unknown, "?"}}; diff --git a/scwx-qt/source/scwx/qt/types/location_types.hpp b/scwx-qt/source/scwx/qt/types/location_types.hpp index 4da1e701..78310ea8 100644 --- a/scwx-qt/source/scwx/qt/types/location_types.hpp +++ b/scwx-qt/source/scwx/qt/types/location_types.hpp @@ -17,6 +17,7 @@ enum class LocationMethod Track, RadarSite, County, + WFO, All, Unknown }; diff --git a/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp b/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp index d36efb07..8159fb69 100644 --- a/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp +++ b/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -108,6 +109,7 @@ public: alertAudioRadarSiteDialog_ {new RadarSiteDialog(self)}, gpsSourceDialog_ {new SerialPortDialog(self)}, countyDialog_ {new CountyDialog(self)}, + wfoDialog_ {new WFODialog(self)}, fontDialog_ {new QFontDialog(self)}, fontCategoryModel_ {new QStandardItemModel(self)}, settings_ {std::initializer_list { @@ -140,6 +142,7 @@ public: &alertAudioRadarSite_, &alertAudioRadius_, &alertAudioCounty_, + &alertAudioWFO_, &hoverTextWrap_, &tooltipMethod_, &placefileTextDropShadowEnabled_, @@ -208,6 +211,7 @@ public: RadarSiteDialog* alertAudioRadarSiteDialog_; SerialPortDialog* gpsSourceDialog_; CountyDialog* countyDialog_; + WFODialog* wfoDialog_; QFontDialog* fontDialog_; QStandardItemModel* fontCategoryModel_; @@ -262,6 +266,7 @@ public: settings::SettingsInterface alertAudioRadarSite_ {}; settings::SettingsInterface alertAudioRadius_ {}; settings::SettingsInterface alertAudioCounty_ {}; + settings::SettingsInterface alertAudioWFO_ {}; std::unordered_map> alertAudioEnabled_ {}; @@ -948,6 +953,8 @@ void SettingsDialogImpl::SetupAudioTab() locationMethod == types::LocationMethod::RadarSite; bool countyEntryEnabled = locationMethod == types::LocationMethod::County; + bool wfoEntryEnabled = + locationMethod == types::LocationMethod::WFO; self_->ui->alertAudioLatitudeSpinBox->setEnabled( coordinateEntryEnabled); @@ -974,6 +981,10 @@ void SettingsDialogImpl::SetupAudioTab() self_->ui->alertAudioCountySelectButton->setEnabled( countyEntryEnabled); self_->ui->resetAlertAudioCountyButton->setEnabled(countyEntryEnabled); + + self_->ui->alertAudioWFOLineEdit->setEnabled(wfoEntryEnabled); + self_->ui->alertAudioWFOSelectButton->setEnabled(wfoEntryEnabled); + self_->ui->resetAlertAudioWFOButton->setEnabled(wfoEntryEnabled); }); settings::AudioSettings& audioSettings = settings::AudioSettings::Instance(); @@ -1194,6 +1205,44 @@ void SettingsDialogImpl::SetupAudioTab() alertAudioCounty_.SetSettingsVariable(audioSettings.alert_county()); alertAudioCounty_.SetEditWidget(self_->ui->alertAudioCountyLineEdit); alertAudioCounty_.SetResetButton(self_->ui->resetAlertAudioCountyButton); + + QObject::connect( + self_->ui->alertAudioWFOSelectButton, + &QAbstractButton::clicked, + self_, + [this]() + { + wfoDialog_->show(); + }); + QObject::connect(wfoDialog_, + &WFODialog::accepted, + self_, + [this]() + { + std::string wfoId = wfoDialog_->wfo_id(); + QString qWFOId = QString::fromStdString(wfoId); + self_->ui->alertAudioWFOLineEdit->setText(qWFOId); + + // setText does not emit the textEdited signal + Q_EMIT self_->ui->alertAudioWFOLineEdit->textEdited( + qWFOId); + }); + QObject::connect(self_->ui->alertAudioWFOLineEdit, + &QLineEdit::textChanged, + self_, + [this](const QString& text) + { + std::string wfoName = + config::CountyDatabase::GetWFOName( + text.toStdString()); + self_->ui->alertAudioWFOLabel->setText( + QString::fromStdString(wfoName)); + }); + + alertAudioWFO_.SetSettingsVariable(audioSettings.alert_wfo()); + alertAudioWFO_.SetEditWidget(self_->ui->alertAudioWFOLineEdit); + alertAudioWFO_.SetResetButton(self_->ui->resetAlertAudioWFOButton); + } void SettingsDialogImpl::SetupTextTab() diff --git a/scwx-qt/source/scwx/qt/ui/settings_dialog.ui b/scwx-qt/source/scwx/qt/ui/settings_dialog.ui index 8d69be46..88dacbbc 100644 --- a/scwx-qt/source/scwx/qt/ui/settings_dialog.ui +++ b/scwx-qt/source/scwx/qt/ui/settings_dialog.ui @@ -136,8 +136,8 @@ 0 0 - 511 - 647 + 274 + 691 @@ -610,8 +610,8 @@ 0 0 - 66 - 18 + 98 + 28 @@ -691,8 +691,15 @@ Alerts - - + + + + County + + + + + ... @@ -702,6 +709,71 @@ + + + + Location Method + + + + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + Longitude + + + + + + + ... + + + + + + + + + + + + + + Latitude + + + + + + + 4 + + + -90.000000000000000 + + + 90.000000000000000 + + + 0.000100000000000 + + + @@ -718,8 +790,8 @@ - - + + ... @@ -729,38 +801,25 @@ - - - - - 0 - 0 - + + + + + :/res/icons/font-awesome-6/play-solid.svg:/res/icons/font-awesome-6/play-solid.svg - - - - County - - - - - + + ... - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - + + - + Radius @@ -780,14 +839,10 @@ - - + + - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + Radar Site @@ -798,32 +853,6 @@ - - - - ... - - - - - - - - - - 4 - - - -90.000000000000000 - - - 90.000000000000000 - - - 0.000100000000000 - - - @@ -832,8 +861,8 @@ - - + + ... @@ -843,20 +872,6 @@ - - - - Latitude - - - - - - - Sound - - - @@ -870,11 +885,25 @@ - - + + + + ... + - :/res/icons/font-awesome-6/play-solid.svg:/res/icons/font-awesome-6/play-solid.svg + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg @@ -891,66 +920,72 @@ - - - - Location Method - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - Radius - - - - - - - Longitude - - - - - - - Radar Site - - - - - - - ... - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - + + + + + 0 + 0 + + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + Sound + + + + + + + WFO + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + + + + + + + + + + + ... + + + diff --git a/scwx-qt/source/scwx/qt/ui/wfo_dialog.cpp b/scwx-qt/source/scwx/qt/ui/wfo_dialog.cpp new file mode 100644 index 00000000..7fd3630e --- /dev/null +++ b/scwx-qt/source/scwx/qt/ui/wfo_dialog.cpp @@ -0,0 +1,142 @@ +#include "wfo_dialog.hpp" +#include "ui_wfo_dialog.h" + +#include +#include + +#include +#include +#include + +namespace scwx +{ +namespace qt +{ +namespace ui +{ + +static const std::string logPrefix_ = "scwx::qt::ui::wfo_dialog"; +static const auto logger_ = scwx::util::Logger::Create(logPrefix_); + +class WFODialog::Impl +{ +public: + explicit Impl(WFODialog* self) : + self_ {self}, + model_ {new QStandardItemModel(self)}, + proxyModel_ {new QSortFilterProxyModel(self)} + { + } + ~Impl() = default; + + void UpdateModel(); + + WFODialog* self_; + QStandardItemModel* model_; + QSortFilterProxyModel* proxyModel_; + + std::string selectedWFO_ {"?"}; +}; + +WFODialog::WFODialog(QWidget* parent) : + QDialog(parent), p {std::make_unique(this)}, ui(new Ui::WFODialog) +{ + ui->setupUi(this); + + p->proxyModel_->setSourceModel(p->model_); + ui->wfoView->setModel(p->proxyModel_); + ui->wfoView->setEditTriggers( + QAbstractItemView::EditTrigger::NoEditTriggers); + ui->wfoView->sortByColumn(0, Qt::SortOrder::AscendingOrder); + ui->wfoView->header()->setSectionResizeMode( + QHeaderView::ResizeMode::Stretch); + + p->UpdateModel(); + + // Button Box + ui->buttonBox->button(QDialogButtonBox::StandardButton::Ok) + ->setEnabled(false); + + connect(ui->wfoView, + &QTreeView::doubleClicked, + this, + [this]() { Q_EMIT accept(); }); + connect( + ui->wfoView->selectionModel(), + &QItemSelectionModel::selectionChanged, + this, + [this](const QItemSelection& selected, const QItemSelection& deselected) + { + if (selected.size() == 0 && deselected.size() == 0) + { + // Items which stay selected but change their index are not + // included in selected and deselected. Thus, this signal might + // be emitted with both selected and deselected empty, if only + // the indices of selected items change. + return; + } + + ui->buttonBox->button(QDialogButtonBox::Ok) + ->setEnabled(selected.size() > 0); + + if (selected.size() > 0) + { + QModelIndex selectedIndex = + p->proxyModel_->mapToSource(selected[0].indexes()[0]); + selectedIndex = p->model_->index(selectedIndex.row(), 1); + QVariant variantData = p->model_->data(selectedIndex); + if (variantData.typeId() == QMetaType::QString) + { + p->selectedWFO_ = variantData.toString().toStdString(); + } + else + { + logger_->warn("Unexpected selection data type"); + p->selectedWFO_ = std::string {"?"}; + } + } + else + { + p->selectedWFO_ = std::string {"?"}; + } + + logger_->debug("Selected: {}", p->selectedWFO_); + }); +} + +WFODialog::~WFODialog() +{ + delete ui; +} + +std::string WFODialog::wfo_id() +{ + return p->selectedWFO_; +} + +void WFODialog::Impl::UpdateModel() +{ + // Clear existing WFOs + model_->clear(); + + // Disable OK button + self_->ui->buttonBox->button(QDialogButtonBox::StandardButton::Ok) + ->setEnabled(false); + + // Reset headers + model_->setHorizontalHeaderLabels({tr("State and City"), tr("ID")}); + + QStandardItem* root = model_->invisibleRootItem(); + + // Add each wfo to the model + for (auto& wfo : config::CountyDatabase::GetWFOs()) + { + root->appendRow( + {new QStandardItem(QString::fromStdString(wfo.second)), + new QStandardItem(QString::fromStdString(wfo.first))}); + } +} + +} // namespace ui +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/wfo_dialog.hpp b/scwx-qt/source/scwx/qt/ui/wfo_dialog.hpp new file mode 100644 index 00000000..ff42ea1b --- /dev/null +++ b/scwx-qt/source/scwx/qt/ui/wfo_dialog.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include + +namespace Ui +{ +class WFODialog; +} + +namespace scwx +{ +namespace qt +{ +namespace ui +{ +class WFODialog : public QDialog +{ + Q_OBJECT + Q_DISABLE_COPY_MOVE(WFODialog) + +public: + explicit WFODialog(QWidget* parent = nullptr); + ~WFODialog(); + + std::string wfo_id(); + +private: + class Impl; + std::unique_ptr p; + Ui::WFODialog* ui; +}; +} // namespace ui +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/wfo_dialog.ui b/scwx-qt/source/scwx/qt/ui/wfo_dialog.ui new file mode 100644 index 00000000..26623489 --- /dev/null +++ b/scwx-qt/source/scwx/qt/ui/wfo_dialog.ui @@ -0,0 +1,101 @@ + + + WFODialog + + + + 0 + 0 + 400 + 400 + + + + Select WFO + + + + + + true + + + 0 + + + true + + + + + + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Orientation::Horizontal + + + QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok + + + + + + + + + + + + buttonBox + accepted() + WFODialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + WFODialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/scwx-qt/tools/generate_counties_db.py b/scwx-qt/tools/generate_counties_db.py index 03872e39..ad6b28d3 100644 --- a/scwx-qt/tools/generate_counties_db.py +++ b/scwx-qt/tools/generate_counties_db.py @@ -34,6 +34,14 @@ def ParseArguments(): nargs = "+", default = [], type = pathlib.Path) + parser.add_argument("-w", "--wfo_dbf", + metavar = "filename", + help = "input wfo database", + dest = "inputWfoDbs_", + action = "extend", + nargs = "+", + default = [], + type = pathlib.Path) parser.add_argument("-o", "--output_db", metavar = "filename", help = "output sqlite database", @@ -49,7 +57,7 @@ def Prepare(dbInfo, outputDb): # Establish SQLite database connection dbInfo.sqlConnection_ = sqlite3.connect(outputDb) - + # Set row factory for name-based access to columns dbInfo.sqlConnection_.row_factory = sqlite3.Row @@ -62,6 +70,11 @@ def Prepare(dbInfo, outputDb): dbInfo.sqlCursor_.execute("""CREATE TABLE states( state TEXT NOT NULL PRIMARY KEY, name TEXT NOT NULL)""") + dbInfo.sqlCursor_.execute("""CREATE TABLE wfos( + id TEXT NOT NULL PRIMARY KEY, + city TEXT NOT NULL, + state TEXT NOT NULL, + city_state TEXT NOT NULL)""") def ProcessCountiesDbf(dbInfo, dbfFilename): # County area type @@ -130,6 +143,22 @@ def ProcessZoneDbf(dbInfo, dbfFilename): if resultRow["name"] != row.NAME: print("Skipping duplicate zone:", fipsId, row.NAME) +def ProcessWfoDbf(dbInfo, dbfFilename): + print("Processing WFO file:", dbfFilename) + + # Read dataframe + dbfTable = gpd.read_file(filename = dbfFilename, + columns = ["FULLSTAID", "CITY", "STATE", "CITYSTATE"], + ignore_geometry = True) + dbfTable.drop_duplicates(inplace = True) + + for row in dbfTable.itertuples(): + try: + dbInfo.sqlCursor_.execute("INSERT INTO wfos VALUES (?, ?, ?, ?)", + (row.FULLSTAID, row.CITY, row.STATE, row.CITYSTATE)) + except: + print("Error inserting WFO:", row.FULLSTAID, row.CITYSTATE) + def PostProcess(dbInfo): # Commit changes and close database dbInfo.sqlConnection_.commit() @@ -148,4 +177,7 @@ for zoneDb in args.inputZoneDbs_: for stateDb in args.inputStateDbs_: ProcessStateDbf(dbInfo, stateDb) +for wfoDb in args.inputWfoDbs_: + ProcessWfoDbf(dbInfo, wfoDb) + PostProcess(dbInfo) diff --git a/test/data b/test/data index 51159935..5a91ded6 160000 --- a/test/data +++ b/test/data @@ -1 +1 @@ -Subproject commit 5115993596cfe6528b7a07c0b16dbd1ae16ce4df +Subproject commit 5a91ded677d4032b0de9370ed767a16708c0ecff