diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake index 77024a0d..b080ae66 100644 --- a/scwx-qt/scwx-qt.cmake +++ b/scwx-qt/scwx-qt.cmake @@ -281,7 +281,8 @@ set(HDR_UI source/scwx/qt/ui/about_dialog.hpp source/scwx/qt/ui/serial_port_dialog.hpp source/scwx/qt/ui/settings_dialog.hpp source/scwx/qt/ui/update_dialog.hpp - source/scwx/qt/ui/wfo_dialog.hpp) + source/scwx/qt/ui/wfo_dialog.hpp + source/scwx/qt/ui/api_key_edit_widget.hpp) set(SRC_UI source/scwx/qt/ui/about_dialog.cpp source/scwx/qt/ui/alert_dialog.cpp source/scwx/qt/ui/alert_dock_widget.cpp @@ -312,7 +313,8 @@ set(SRC_UI source/scwx/qt/ui/about_dialog.cpp source/scwx/qt/ui/settings_dialog.cpp source/scwx/qt/ui/serial_port_dialog.cpp source/scwx/qt/ui/update_dialog.cpp - source/scwx/qt/ui/wfo_dialog.cpp) + source/scwx/qt/ui/wfo_dialog.cpp + source/scwx/qt/ui/api_key_edit_widget.cpp) set(UI_UI source/scwx/qt/ui/about_dialog.ui source/scwx/qt/ui/alert_dialog.ui source/scwx/qt/ui/alert_dock_widget.ui diff --git a/scwx-qt/source/scwx/qt/ui/api_key_edit_widget.cpp b/scwx-qt/source/scwx/qt/ui/api_key_edit_widget.cpp new file mode 100644 index 00000000..15adf525 --- /dev/null +++ b/scwx-qt/source/scwx/qt/ui/api_key_edit_widget.cpp @@ -0,0 +1,107 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace scwx::qt::ui; + +static const std::string logPrefix_ = "scwx::qt::ui::setup::api_key"; +static const auto logger_ = scwx::util::Logger::Create(logPrefix_); + +QApiKeyEdit::QApiKeyEdit(QWidget* parent) : + QLineEdit(parent), networkAccessManager_(new QNetworkAccessManager(this)) +{ + const QIcon icon = + QApplication::style()->standardIcon(QStyle::SP_BrowserReload); + testAction_ = addAction(icon, QLineEdit::TrailingPosition); + testAction_->setIconText(tr("Test Key")); + testAction_->setToolTip(tr("Test the API key for this provider")); + + connect(testAction_, &QAction::triggered, this, &QApiKeyEdit::apiTest); + connect(networkAccessManager_, + &QNetworkAccessManager::finished, + this, + &QApiKeyEdit::apiTestFinished); + + // Reset test icon when text changes + connect(this, + &QLineEdit::textChanged, + this, + [this, icon]() { testAction_->setIcon(icon); }); +} + +void QApiKeyEdit::apiTest() +{ + QNetworkRequest req; + req.setTransferTimeout(5000); + + switch (provider_) + { + case map::MapProvider::Mapbox: + { + QUrl url("https://api.mapbox.com/v4/mapbox.mapbox-streets-v8/1/0/0.mvt"); + logger_->debug("Testing MapProvider::Mapbox API key at {}", + url.toString().toStdString()); + QUrlQuery query; + query.addQueryItem("access_token", text()); + url.setQuery(query); + req.setUrl(url); + break; + } + case map::MapProvider::MapTiler: + { + QUrl url("https://api.maptiler.com/maps/streets-v2/"); + logger_->debug("Testing MapProvider::MapTiler API key at {}", + url.toString().toStdString()); + QUrlQuery query; + query.addQueryItem("key", text()); + url.setQuery(query); + req.setUrl(url); + break; + } + default: + { + logger_->warn("Cannot test MapProvider::Unknown API key"); + break; + } + } + + networkAccessManager_->get(req); +} + +void QApiKeyEdit::apiTestFinished(QNetworkReply* reply) +{ + switch (reply->error()) + { + case QNetworkReply::NoError: + { + logger_->info("QApiKeyEdit: test success"); + QToolTip::showText(mapToGlobal(QPoint()), tr("Key was valid")); + testAction_->setIcon( + QApplication::style()->standardIcon(QStyle::SP_DialogApplyButton)); + Q_EMIT apiTestSucceeded(); + break; + } + default: + { + const char* errStr = + QMetaEnum::fromType().valueToKey( + reply->error()); + logger_->warn("QApiKeyEdit: test failed, got {} from {}", + errStr, + reply->url().host().toStdString()); + QToolTip::showText(mapToGlobal(QPoint()), tr("Invalid key")); + testAction_->setIcon( + QApplication::style()->standardIcon(QStyle::SP_DialogCancelButton)); + Q_EMIT apiTestFailed(reply->error()); + break; + } + } +} diff --git a/scwx-qt/source/scwx/qt/ui/api_key_edit_widget.hpp b/scwx-qt/source/scwx/qt/ui/api_key_edit_widget.hpp new file mode 100644 index 00000000..074e0b55 --- /dev/null +++ b/scwx-qt/source/scwx/qt/ui/api_key_edit_widget.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include + +class QNetworkAccessManager; + +namespace scwx::qt::ui +{ + +class QApiKeyEdit : public QLineEdit +{ + Q_OBJECT + +public: + QApiKeyEdit(QWidget* parent = nullptr); + + map::MapProvider getMapProvider() const { return provider_; } + + void setMapProvider(const map::MapProvider provider) + { + provider_ = provider; + } + +signals: + void apiTestSucceeded(); + void apiTestFailed(QNetworkReply::NetworkError error); + +private slots: + void apiTest(); + void apiTestFinished(QNetworkReply* reply); + +protected: + map::MapProvider provider_ {map::MapProvider::Unknown}; + QNetworkAccessManager* networkAccessManager_ {}; + QAction* testAction_ {}; +}; + +} // namespace scwx::qt::ui diff --git a/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp b/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp index 5491bb21..7ce55037 100644 --- a/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp +++ b/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp @@ -669,11 +669,14 @@ void SettingsDialogImpl::SetupGeneralTab() map::GetMapProviderName); mapProvider_.SetResetButton(self_->ui->resetMapProviderButton); + self_->ui->mapboxApiKeyLineEdit->setMapProvider(map::MapProvider::Mapbox); mapboxApiKey_.SetSettingsVariable(generalSettings.mapbox_api_key()); mapboxApiKey_.SetEditWidget(self_->ui->mapboxApiKeyLineEdit); mapboxApiKey_.SetResetButton(self_->ui->resetMapboxApiKeyButton); mapboxApiKey_.EnableTrimming(); + self_->ui->mapTilerApiKeyLineEdit->setMapProvider( + map::MapProvider::MapTiler); mapTilerApiKey_.SetSettingsVariable(generalSettings.maptiler_api_key()); mapTilerApiKey_.SetEditWidget(self_->ui->mapTilerApiKeyLineEdit); mapTilerApiKey_.SetResetButton(self_->ui->resetMapTilerApiKeyButton); diff --git a/scwx-qt/source/scwx/qt/ui/settings_dialog.ui b/scwx-qt/source/scwx/qt/ui/settings_dialog.ui index be599bff..bb2389bc 100644 --- a/scwx-qt/source/scwx/qt/ui/settings_dialog.ui +++ b/scwx-qt/source/scwx/qt/ui/settings_dialog.ui @@ -256,14 +256,14 @@ - + QLineEdit::EchoMode::Password - + QLineEdit::EchoMode::Password @@ -1389,6 +1389,13 @@ + + + scwx::qt::ui::QApiKeyEdit + QLineEdit +
scwx/qt/ui/api_key_edit_widget.hpp
+
+
diff --git a/scwx-qt/source/scwx/qt/ui/setup/map_provider_page.cpp b/scwx-qt/source/scwx/qt/ui/setup/map_provider_page.cpp index 0e5c3f98..b4d7038a 100644 --- a/scwx-qt/source/scwx/qt/ui/setup/map_provider_page.cpp +++ b/scwx-qt/source/scwx/qt/ui/setup/map_provider_page.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -18,13 +19,7 @@ #include #include -namespace scwx -{ -namespace qt -{ -namespace ui -{ -namespace setup +namespace scwx::qt::ui::setup { static const std::unordered_map kUrl_ { @@ -33,8 +28,8 @@ static const std::unordered_map kUrl_ { struct MapProviderGroup { - QLabel* apiKeyLabel_ {}; - QLineEdit* apiKeyEdit_ {}; + QLabel* apiKeyLabel_ {}; + QApiKeyEdit* apiKeyEdit_ {}; }; class MapProviderPage::Impl @@ -45,7 +40,9 @@ public: void SelectMapProvider(const QString& text); void SelectMapProvider(map::MapProvider mapProvider); - void SetupMapProviderGroup(MapProviderGroup& group, int row); + void SetupMapProviderGroup(const map::MapProvider mapProvider, + MapProviderGroup& group, + int row); void SetupSettingsInterface(); static void SetGroupVisible(MapProviderGroup& group, bool visible); @@ -122,8 +119,8 @@ MapProviderPage::MapProviderPage(QWidget* parent) : p->buttonLayout_->addItem(p->buttonSpacer_); p->buttonFrame_->setLayout(p->buttonLayout_); - p->SetupMapProviderGroup(p->mapboxGroup_, 1); - p->SetupMapProviderGroup(p->maptilerGroup_, 2); + p->SetupMapProviderGroup(map::MapProvider::Mapbox, p->mapboxGroup_, 1); + p->SetupMapProviderGroup(map::MapProvider::MapTiler, p->maptilerGroup_, 2); // Overall layout p->layout_ = new QVBoxLayout(this); @@ -159,11 +156,12 @@ MapProviderPage::MapProviderPage(QWidget* parent) : MapProviderPage::~MapProviderPage() = default; -void MapProviderPage::Impl::SetupMapProviderGroup(MapProviderGroup& group, - int row) +void MapProviderPage::Impl::SetupMapProviderGroup( + const map::MapProvider provider, MapProviderGroup& group, int row) { group.apiKeyLabel_ = new QLabel(self_); - group.apiKeyEdit_ = new QLineEdit(self_); + group.apiKeyEdit_ = new QApiKeyEdit(self_); + group.apiKeyEdit_->setMapProvider(provider); group.apiKeyLabel_->setText(tr("API Key")); @@ -171,7 +169,7 @@ void MapProviderPage::Impl::SetupMapProviderGroup(MapProviderGroup& group, mapProviderLayout_->addWidget(group.apiKeyEdit_, row, 1, 1, 1); QObject::connect(group.apiKeyEdit_, - &QLineEdit::textChanged, + &QApiKeyEdit::textChanged, self_, &QWizardPage::completeChanged); } @@ -292,7 +290,4 @@ bool MapProviderPage::IsRequired() return (mapboxApiKey.size() <= 1 && maptilerApiKey.size() <= 1); } -} // namespace setup -} // namespace ui -} // namespace qt -} // namespace scwx +} // namespace scwx::qt::ui::setup