Merge pull request #399 from aware70/add-map-api-key-validity-check

Add map API key test button to initial dialog and settings dialog
This commit is contained in:
Dan Paulat 2025-03-28 01:10:36 -05:00 committed by GitHub
commit c9ead60dd4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 176 additions and 22 deletions

View file

@ -255,6 +255,7 @@ set(HDR_UI source/scwx/qt/ui/about_dialog.hpp
source/scwx/qt/ui/alert_dialog.hpp
source/scwx/qt/ui/alert_dock_widget.hpp
source/scwx/qt/ui/animation_dock_widget.hpp
source/scwx/qt/ui/api_key_edit_widget.hpp
source/scwx/qt/ui/collapsible_group.hpp
source/scwx/qt/ui/county_dialog.hpp
source/scwx/qt/ui/download_dialog.hpp
@ -286,6 +287,7 @@ 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
source/scwx/qt/ui/animation_dock_widget.cpp
source/scwx/qt/ui/api_key_edit_widget.cpp
source/scwx/qt/ui/collapsible_group.cpp
source/scwx/qt/ui/county_dialog.cpp
source/scwx/qt/ui/download_dialog.cpp

View file

@ -0,0 +1,107 @@
#include <scwx/qt/ui/api_key_edit_widget.hpp>
#include <scwx/util/logger.hpp>
#include <QMetaEnum>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QNetworkAccessManager>
#include <QApplication>
#include <QStyle>
#include <QUrlQuery>
#include <QToolTip>
using namespace scwx::qt::ui;
static const std::string logPrefix_ = "scwx::qt::ui::QApiKeyEdit";
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<QNetworkReply::NetworkError>().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;
}
}
}

View file

@ -0,0 +1,40 @@
#pragma once
#include <scwx/qt/map/map_provider.hpp>
#include <QNetworkReply>
#include <QLineEdit>
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

View file

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

View file

@ -256,14 +256,14 @@
</widget>
</item>
<item row="13" column="2">
<widget class="QLineEdit" name="mapTilerApiKeyLineEdit">
<widget class="scwx::qt::ui::QApiKeyEdit" name="mapTilerApiKeyLineEdit">
<property name="echoMode">
<enum>QLineEdit::EchoMode::Password</enum>
</property>
</widget>
</item>
<item row="12" column="2">
<widget class="QLineEdit" name="mapboxApiKeyLineEdit">
<widget class="scwx::qt::ui::QApiKeyEdit" name="mapboxApiKeyLineEdit">
<property name="echoMode">
<enum>QLineEdit::EchoMode::Password</enum>
</property>
@ -1389,6 +1389,13 @@
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>scwx::qt::ui::QApiKeyEdit</class>
<extends>QLineEdit</extends>
<header>scwx/qt/ui/api_key_edit_widget.hpp</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../../../scwx-qt.qrc"/>
</resources>

View file

@ -1,4 +1,5 @@
#include <scwx/qt/ui/setup/map_provider_page.hpp>
#include <scwx/qt/ui/api_key_edit_widget.hpp>
#include <scwx/qt/manager/settings_manager.hpp>
#include <scwx/qt/map/map_provider.hpp>
#include <scwx/qt/settings/general_settings.hpp>
@ -18,13 +19,7 @@
#include <QVBoxLayout>
#include <boost/algorithm/string.hpp>
namespace scwx
{
namespace qt
{
namespace ui
{
namespace setup
namespace scwx::qt::ui::setup
{
static const std::unordered_map<map::MapProvider, QUrl> kUrl_ {
@ -34,7 +29,7 @@ static const std::unordered_map<map::MapProvider, QUrl> kUrl_ {
struct MapProviderGroup
{
QLabel* apiKeyLabel_ {};
QLineEdit* apiKeyEdit_ {};
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