Merge pull request #234 from dpaulat/feature/custom-map-style

Allow Custom Map Styles
This commit is contained in:
Dan Paulat 2024-06-22 00:58:39 -05:00 committed by GitHub
commit 7161a5a3b2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 278 additions and 29 deletions

View file

@ -139,6 +139,16 @@ public:
} }
~MainWindowImpl() ~MainWindowImpl()
{ {
auto& generalSettings = settings::GeneralSettings::Instance();
auto& customStyleUrl = generalSettings.custom_style_url();
auto& customStyleDrawLayer = generalSettings.custom_style_draw_layer();
customStyleUrl.UnregisterValueChangedCallback(
customStyleUrlChangedCallbackUuid_);
customStyleDrawLayer.UnregisterValueChangedCallback(
customStyleDrawLayerChangedCallbackUuid_);
clockTimer_.stop(); clockTimer_.stop();
threadPool_.join(); threadPool_.join();
} }
@ -153,6 +163,7 @@ public:
void ConnectOtherSignals(); void ConnectOtherSignals();
void HandleFocusChange(QWidget* focused); void HandleFocusChange(QWidget* focused);
void InitializeLayerDisplayActions(); void InitializeLayerDisplayActions();
void PopulateCustomMapStyle();
void PopulateMapStyles(); void PopulateMapStyles();
void SelectElevation(map::MapWidget* mapWidget, float elevation); void SelectElevation(map::MapWidget* mapWidget, float elevation);
void SelectRadarProduct(map::MapWidget* mapWidget, void SelectRadarProduct(map::MapWidget* mapWidget,
@ -202,6 +213,10 @@ public:
QTimer clockTimer_ {}; QTimer clockTimer_ {};
bool customStyleAvailable_ {false};
boost::uuids::uuid customStyleDrawLayerChangedCallbackUuid_ {};
boost::uuids::uuid customStyleUrlChangedCallbackUuid_ {};
std::shared_ptr<manager::AlertManager> alertManager_; std::shared_ptr<manager::AlertManager> alertManager_;
std::shared_ptr<manager::HotkeyManager> hotkeyManager_ { std::shared_ptr<manager::HotkeyManager> hotkeyManager_ {
manager::HotkeyManager::Instance()}; manager::HotkeyManager::Instance()};
@ -750,7 +765,8 @@ void MainWindowImpl::ConfigureMapStyles()
{ {
std::string styleName = mapSettings.map_style(i).GetValue(); std::string styleName = mapSettings.map_style(i).GetValue();
if (std::find_if(mapProviderInfo.mapStyles_.cbegin(), if ((customStyleAvailable_ && styleName == "Custom") ||
std::find_if(mapProviderInfo.mapStyles_.cbegin(),
mapProviderInfo.mapStyles_.cend(), mapProviderInfo.mapStyles_.cend(),
[&](const auto& mapStyle) { [&](const auto& mapStyle) {
return mapStyle.name_ == styleName; return mapStyle.name_ == styleName;
@ -1262,6 +1278,36 @@ void MainWindowImpl::HandleFocusChange(QWidget* focused)
} }
} }
void MainWindowImpl::PopulateCustomMapStyle()
{
auto& generalSettings = settings::GeneralSettings::Instance();
auto customStyleUrl = generalSettings.custom_style_url().GetValue();
auto customStyleDrawLayer =
generalSettings.custom_style_draw_layer().GetValue();
bool newCustomStyleAvailable =
!customStyleUrl.empty() && !customStyleDrawLayer.empty();
if (newCustomStyleAvailable != customStyleAvailable_)
{
static const QString kCustom {"Custom"};
if (newCustomStyleAvailable)
{
mainWindow_->ui->mapStyleComboBox->addItem(kCustom);
}
else
{
int index = mainWindow_->ui->mapStyleComboBox->findText(kCustom);
mainWindow_->ui->mapStyleComboBox->removeItem(index);
}
customStyleAvailable_ = newCustomStyleAvailable;
}
}
void MainWindowImpl::PopulateMapStyles() void MainWindowImpl::PopulateMapStyles()
{ {
const auto& mapProviderInfo = map::GetMapProviderInfo(mapProvider_); const auto& mapProviderInfo = map::GetMapProviderInfo(mapProvider_);
@ -1270,6 +1316,22 @@ void MainWindowImpl::PopulateMapStyles()
mainWindow_->ui->mapStyleComboBox->addItem( mainWindow_->ui->mapStyleComboBox->addItem(
QString::fromStdString(mapStyle.name_)); QString::fromStdString(mapStyle.name_));
} }
auto& generalSettings = settings::GeneralSettings::Instance();
auto& customStyleUrl = generalSettings.custom_style_url();
auto& customStyleDrawLayer = generalSettings.custom_style_draw_layer();
customStyleUrlChangedCallbackUuid_ =
customStyleUrl.RegisterValueChangedCallback(
[this]([[maybe_unused]] const std::string& value)
{ PopulateCustomMapStyle(); });
customStyleDrawLayerChangedCallbackUuid_ =
customStyleDrawLayer.RegisterValueChangedCallback(
[this]([[maybe_unused]] const std::string& value)
{ PopulateCustomMapStyle(); });
PopulateCustomMapStyle();
} }
void MainWindowImpl::SelectElevation(map::MapWidget* mapWidget, float elevation) void MainWindowImpl::SelectElevation(map::MapWidget* mapWidget, float elevation)

View file

@ -178,6 +178,11 @@ static const std::unordered_map<MapProvider, MapProviderInfo> mapProviderInfo_ {
.drawBelow_ {"aeroway_runway", "Aeroway"}}}}}, .drawBelow_ {"aeroway_runway", "Aeroway"}}}}},
{MapProvider::Unknown, MapProviderInfo {}}}; {MapProvider::Unknown, MapProviderInfo {}}};
bool MapStyle::IsValid() const
{
return !url_.empty() && !drawBelow_.empty();
}
MapProvider GetMapProvider(const std::string& name) MapProvider GetMapProvider(const std::string& name)
{ {
auto result = auto result =

View file

@ -28,6 +28,8 @@ struct MapStyle
std::string name_; std::string name_;
std::string url_; std::string url_;
std::vector<std::string> drawBelow_; std::vector<std::string> drawBelow_;
bool IsValid() const;
}; };
struct MapProviderInfo struct MapProviderInfo

View file

@ -35,6 +35,7 @@
#include <boost/algorithm/string/trim.hpp> #include <boost/algorithm/string/trim.hpp>
#include <boost/asio/post.hpp> #include <boost/asio/post.hpp>
#include <boost/asio/thread_pool.hpp> #include <boost/asio/thread_pool.hpp>
#include <boost/range/join.hpp>
#include <boost/uuid/random_generator.hpp> #include <boost/uuid/random_generator.hpp>
#include <fmt/format.h> #include <fmt/format.h>
#include <imgui.h> #include <imgui.h>
@ -117,11 +118,15 @@ public:
// Initialize ImGui Qt backend // Initialize ImGui Qt backend
ImGui_ImplQt_Init(); ImGui_ImplQt_Init();
InitializeCustomStyles();
ConnectSignals(); ConnectSignals();
} }
~MapWidgetImpl() ~MapWidgetImpl()
{ {
DeinitializeCustomStyles();
// Set ImGui Context // Set ImGui Context
ImGui::SetCurrentContext(imGuiContext_); ImGui::SetCurrentContext(imGuiContext_);
@ -149,10 +154,12 @@ public:
const std::string& before); const std::string& before);
void ConnectMapSignals(); void ConnectMapSignals();
void ConnectSignals(); void ConnectSignals();
void DeinitializeCustomStyles() const;
void HandleHotkeyPressed(types::Hotkey hotkey, bool isAutoRepeat); void HandleHotkeyPressed(types::Hotkey hotkey, bool isAutoRepeat);
void HandleHotkeyReleased(types::Hotkey hotkey); void HandleHotkeyReleased(types::Hotkey hotkey);
void HandleHotkeyUpdates(); void HandleHotkeyUpdates();
void ImGuiCheckFonts(); void ImGuiCheckFonts();
void InitializeCustomStyles();
void InitializeNewRadarProductView(const std::string& colorPalette); void InitializeNewRadarProductView(const std::string& colorPalette);
void RadarProductManagerConnect(); void RadarProductManagerConnect();
void RadarProductManagerDisconnect(); void RadarProductManagerDisconnect();
@ -187,9 +194,15 @@ public:
std::vector<std::shared_ptr<GenericLayer>> genericLayers_ {}; std::vector<std::shared_ptr<GenericLayer>> genericLayers_ {};
const std::vector<MapStyle> emptyStyles_ {};
std::vector<MapStyle> customStyles_ {
MapStyle {.name_ {"Custom"}, .url_ {}, .drawBelow_ {}}};
QStringList styleLayers_; QStringList styleLayers_;
types::LayerVector customLayers_; types::LayerVector customLayers_;
boost::uuids::uuid customStyleUrlChangedCallbackId_ {};
boost::uuids::uuid customStyleDrawBelowChangedCallbackId_ {};
ImGuiContext* imGuiContext_; ImGuiContext* imGuiContext_;
std::string imGuiContextName_; std::string imGuiContextName_;
bool imGuiRendererInitialized_; bool imGuiRendererInitialized_;
@ -269,6 +282,48 @@ MapWidget::~MapWidget()
makeCurrent(); makeCurrent();
} }
void MapWidgetImpl::InitializeCustomStyles()
{
auto& generalSettings = settings::GeneralSettings::Instance();
auto& customStyleUrl = generalSettings.custom_style_url();
auto& customStyleDrawLayer = generalSettings.custom_style_draw_layer();
auto& customStyle = customStyles_.at(0);
customStyle.url_ = customStyleUrl.GetValue();
customStyle.drawBelow_.push_back(customStyleDrawLayer.GetValue());
customStyleUrlChangedCallbackId_ =
customStyleUrl.RegisterValueChangedCallback(
[this](const std::string& url) { customStyles_[0].url_ = url; });
customStyleDrawBelowChangedCallbackId_ =
customStyleDrawLayer.RegisterValueChangedCallback(
[this](const std::string& drawLayer)
{
if (!drawLayer.empty())
{
customStyles_[0].drawBelow_ = {drawLayer};
}
else
{
customStyles_[0].drawBelow_.clear();
}
});
}
void MapWidgetImpl::DeinitializeCustomStyles() const
{
auto& generalSettings = settings::GeneralSettings::Instance();
auto& customStyleUrl = generalSettings.custom_style_url();
auto& customStyleDrawLayer = generalSettings.custom_style_draw_layer();
customStyleUrl.UnregisterValueChangedCallback(
customStyleUrlChangedCallbackId_);
customStyleDrawLayer.UnregisterValueChangedCallback(
customStyleDrawBelowChangedCallbackId_);
}
void MapWidgetImpl::ConnectMapSignals() void MapWidgetImpl::ConnectMapSignals()
{ {
connect(map_.get(), connect(map_.get(),
@ -283,8 +338,8 @@ void MapWidgetImpl::ConnectMapSignals()
QTextDocument document {}; QTextDocument document {};
document.setHtml(copyrightsHtml); document.setHtml(copyrightsHtml);
// HTML cannot currently be included in ImGui windows. Where links // HTML cannot currently be included in ImGui windows. Where
// can't be included, remove "Improve this map". // links can't be included, remove "Improve this map".
std::string copyrights {document.toPlainText().toStdString()}; std::string copyrights {document.toPlainText().toStdString()};
boost::erase_all(copyrights, "Improve this map"); boost::erase_all(copyrights, "Improve this map");
boost::trim_right(copyrights); boost::trim_right(copyrights);
@ -924,7 +979,16 @@ void MapWidget::SetMapStyle(const std::string& styleName)
{ {
const auto mapProvider = p->context_->map_provider(); const auto mapProvider = p->context_->map_provider();
const auto& mapProviderInfo = GetMapProviderInfo(mapProvider); const auto& mapProviderInfo = GetMapProviderInfo(mapProvider);
auto& styles = mapProviderInfo.mapStyles_; auto& fixedStyles = mapProviderInfo.mapStyles_;
auto styles = boost::join(fixedStyles,
p->customStyles_[0].IsValid() ? p->customStyles_ :
p->emptyStyles_);
if (p->currentStyleIndex_ >= styles.size())
{
p->currentStyleIndex_ = 0;
}
for (size_t i = 0u; i < styles.size(); ++i) for (size_t i = 0u; i < styles.size(); ++i)
{ {
@ -937,7 +1001,7 @@ void MapWidget::SetMapStyle(const std::string& styleName)
util::maplibre::SetMapStyleUrl(p->context_, styles[i].url_); util::maplibre::SetMapStyleUrl(p->context_, styles[i].url_);
if (++p->currentStyleIndex_ == styles.size()) if (++p->currentStyleIndex_ >= styles.size())
{ {
p->currentStyleIndex_ = 0; p->currentStyleIndex_ = 0;
} }
@ -974,7 +1038,16 @@ void MapWidget::changeStyle()
{ {
const auto mapProvider = p->context_->map_provider(); const auto mapProvider = p->context_->map_provider();
const auto& mapProviderInfo = GetMapProviderInfo(mapProvider); const auto& mapProviderInfo = GetMapProviderInfo(mapProvider);
auto& styles = mapProviderInfo.mapStyles_; auto& fixedStyles = mapProviderInfo.mapStyles_;
auto styles = boost::join(fixedStyles,
p->customStyles_[0].IsValid() ? p->customStyles_ :
p->emptyStyles_);
if (p->currentStyleIndex_ >= styles.size())
{
p->currentStyleIndex_ = 0;
}
p->currentStyle_ = &styles[p->currentStyleIndex_]; p->currentStyle_ = &styles[p->currentStyleIndex_];
@ -983,7 +1056,7 @@ void MapWidget::changeStyle()
util::maplibre::SetMapStyleUrl(p->context_, util::maplibre::SetMapStyleUrl(p->context_,
styles[p->currentStyleIndex_].url_); styles[p->currentStyleIndex_].url_);
if (++p->currentStyleIndex_ == styles.size()) if (++p->currentStyleIndex_ >= styles.size())
{ {
p->currentStyleIndex_ = 0; p->currentStyleIndex_ = 0;
} }
@ -1011,7 +1084,16 @@ std::string MapWidgetImpl::FindMapSymbologyLayer()
{ {
// Perform case-insensitive matching // Perform case-insensitive matching
RE2 re {"(?i)" + styleLayer}; RE2 re {"(?i)" + styleLayer};
if (re.ok())
{
return RE2::FullMatch(layer, re); return RE2::FullMatch(layer, re);
}
else
{
// Fall back to basic comparison if RE
// doesn't compile
return layer == styleLayer;
}
}); });
if (it != currentStyle_->drawBelow_.cend()) if (it != currentStyle_->drawBelow_.cend())
@ -1618,8 +1700,8 @@ void MapWidgetImpl::RadarProductManagerConnect()
// Select loaded record // Select loaded record
auto record = request->radar_product_record(); auto record = request->radar_product_record();
// Validate record, and verify current map context still // Validate record, and verify current map context
// displays site and product // still displays site and product
if (record != nullptr && if (record != nullptr &&
radarProductManager_ != nullptr && radarProductManager_ != nullptr &&
radarProductManager_->radar_id() == radarProductManager_->radar_id() ==

View file

@ -52,6 +52,7 @@ public:
antiAliasingEnabled_.SetDefault(true); antiAliasingEnabled_.SetDefault(true);
clockFormat_.SetDefault(defaultClockFormatValue); clockFormat_.SetDefault(defaultClockFormatValue);
customStyleDrawLayer_.SetDefault(".*\\.annotations\\.points");
debugEnabled_.SetDefault(false); debugEnabled_.SetDefault(false);
defaultAlertAction_.SetDefault(defaultDefaultAlertActionValue); defaultAlertAction_.SetDefault(defaultDefaultAlertActionValue);
defaultRadarSite_.SetDefault("KLSX"); defaultRadarSite_.SetDefault("KLSX");
@ -93,10 +94,17 @@ public:
nmeaBaudRate_.SetMinimum(1); nmeaBaudRate_.SetMinimum(1);
nmeaBaudRate_.SetMaximum(999999999); nmeaBaudRate_.SetMaximum(999999999);
customStyleDrawLayer_.SetTransform([](const std::string& value)
{ return boost::trim_copy(value); });
customStyleUrl_.SetTransform([](const std::string& value)
{ return boost::trim_copy(value); });
clockFormat_.SetValidator( clockFormat_.SetValidator(
SCWX_SETTINGS_ENUM_VALIDATOR(scwx::util::ClockFormat, SCWX_SETTINGS_ENUM_VALIDATOR(scwx::util::ClockFormat,
scwx::util::ClockFormatIterator(), scwx::util::ClockFormatIterator(),
scwx::util::GetClockFormatName)); scwx::util::GetClockFormatName));
customStyleDrawLayer_.SetValidator([](const std::string& value)
{ return !value.empty(); });
defaultAlertAction_.SetValidator( defaultAlertAction_.SetValidator(
SCWX_SETTINGS_ENUM_VALIDATOR(types::AlertAction, SCWX_SETTINGS_ENUM_VALIDATOR(types::AlertAction,
types::AlertActionIterator(), types::AlertActionIterator(),
@ -130,6 +138,9 @@ public:
SettingsVariable<bool> antiAliasingEnabled_ {"anti_aliasing_enabled"}; SettingsVariable<bool> antiAliasingEnabled_ {"anti_aliasing_enabled"};
SettingsVariable<std::string> clockFormat_ {"clock_format"}; SettingsVariable<std::string> clockFormat_ {"clock_format"};
SettingsVariable<std::string> customStyleDrawLayer_ {
"custom_style_draw_layer"};
SettingsVariable<std::string> customStyleUrl_ {"custom_style_url"};
SettingsVariable<bool> debugEnabled_ {"debug_enabled"}; SettingsVariable<bool> debugEnabled_ {"debug_enabled"};
SettingsVariable<std::string> defaultAlertAction_ {"default_alert_action"}; SettingsVariable<std::string> defaultAlertAction_ {"default_alert_action"};
SettingsVariable<std::string> defaultRadarSite_ {"default_radar_site"}; SettingsVariable<std::string> defaultRadarSite_ {"default_radar_site"};
@ -158,8 +169,10 @@ public:
GeneralSettings::GeneralSettings() : GeneralSettings::GeneralSettings() :
SettingsCategory("general"), p(std::make_unique<Impl>()) SettingsCategory("general"), p(std::make_unique<Impl>())
{ {
RegisterVariables({&p->antiAliasingEnabled_, // RegisterVariables({&p->antiAliasingEnabled_,
&p->clockFormat_, &p->clockFormat_,
&p->customStyleDrawLayer_,
&p->customStyleUrl_,
&p->debugEnabled_, &p->debugEnabled_,
&p->defaultAlertAction_, &p->defaultAlertAction_,
&p->defaultRadarSite_, &p->defaultRadarSite_,
@ -201,6 +214,16 @@ SettingsVariable<std::string>& GeneralSettings::clock_format() const
return p->clockFormat_; return p->clockFormat_;
} }
SettingsVariable<std::string>& GeneralSettings::custom_style_draw_layer() const
{
return p->customStyleDrawLayer_;
}
SettingsVariable<std::string>& GeneralSettings::custom_style_url() const
{
return p->customStyleUrl_;
}
SettingsVariable<bool>& GeneralSettings::debug_enabled() const SettingsVariable<bool>& GeneralSettings::debug_enabled() const
{ {
return p->debugEnabled_; return p->debugEnabled_;
@ -340,6 +363,8 @@ bool operator==(const GeneralSettings& lhs, const GeneralSettings& rhs)
{ {
return (lhs.p->antiAliasingEnabled_ == rhs.p->antiAliasingEnabled_ && return (lhs.p->antiAliasingEnabled_ == rhs.p->antiAliasingEnabled_ &&
lhs.p->clockFormat_ == rhs.p->clockFormat_ && lhs.p->clockFormat_ == rhs.p->clockFormat_ &&
lhs.p->customStyleDrawLayer_ == rhs.p->customStyleDrawLayer_ &&
lhs.p->customStyleUrl_ == rhs.p->customStyleUrl_ &&
lhs.p->debugEnabled_ == rhs.p->debugEnabled_ && lhs.p->debugEnabled_ == rhs.p->debugEnabled_ &&
lhs.p->defaultAlertAction_ == rhs.p->defaultAlertAction_ && lhs.p->defaultAlertAction_ == rhs.p->defaultAlertAction_ &&
lhs.p->defaultRadarSite_ == rhs.p->defaultRadarSite_ && lhs.p->defaultRadarSite_ == rhs.p->defaultRadarSite_ &&

View file

@ -27,6 +27,8 @@ public:
SettingsVariable<bool>& anti_aliasing_enabled() const; SettingsVariable<bool>& anti_aliasing_enabled() const;
SettingsVariable<std::string>& clock_format() const; SettingsVariable<std::string>& clock_format() const;
SettingsVariable<std::string>& custom_style_draw_layer() const;
SettingsVariable<std::string>& custom_style_url() const;
SettingsVariable<bool>& debug_enabled() const; SettingsVariable<bool>& debug_enabled() const;
SettingsVariable<std::string>& default_alert_action() const; SettingsVariable<std::string>& default_alert_action() const;
SettingsVariable<std::string>& default_radar_site() const; SettingsVariable<std::string>& default_radar_site() const;

View file

@ -30,6 +30,7 @@ public:
std::optional<T> staged_ {}; std::optional<T> staged_ {};
std::optional<T> minimum_ {}; std::optional<T> minimum_ {};
std::optional<T> maximum_ {}; std::optional<T> maximum_ {};
std::function<T(const T&)> transform_ {};
std::function<bool(const T&)> validator_ {nullptr}; std::function<bool(const T&)> validator_ {nullptr};
boost::unordered_flat_map<boost::uuids::uuid, ValueCallbackFunction> boost::unordered_flat_map<boost::uuids::uuid, ValueCallbackFunction>
@ -79,7 +80,7 @@ bool SettingsVariable<T>::SetValue(const T& value)
if (Validate(value)) if (Validate(value))
{ {
p->value_ = value; p->value_ = (p->transform_ != nullptr) ? p->transform_(value) : value;
validated = true; validated = true;
for (auto& callback : p->valueChangedCallbackFunctions_) for (auto& callback : p->valueChangedCallbackFunctions_)
@ -102,7 +103,7 @@ bool SettingsVariable<T>::SetValueOrDefault(const T& value)
if (Validate(value)) if (Validate(value))
{ {
p->value_ = value; p->value_ = (p->transform_ != nullptr) ? p->transform_(value) : value;
validated = true; validated = true;
} }
else if (p->minimum_.has_value() && value < p->minimum_) else if (p->minimum_.has_value() && value < p->minimum_)
@ -182,9 +183,11 @@ bool SettingsVariable<T>::StageValue(const T& value)
if (Validate(value)) if (Validate(value))
{ {
if (p->value_ != value) T transformed = (p->transform_ != nullptr) ? p->transform_(value) : value;
if (p->value_ != transformed)
{ {
p->staged_ = value; p->staged_ = transformed;
} }
else else
{ {
@ -195,7 +198,7 @@ bool SettingsVariable<T>::StageValue(const T& value)
for (auto& callback : p->valueStagedCallbackFunctions_) for (auto& callback : p->valueStagedCallbackFunctions_)
{ {
callback.second(value); callback.second(transformed);
} }
} }
@ -285,6 +288,12 @@ std::optional<T> SettingsVariable<T>::GetMaximum() const
return p->maximum_; return p->maximum_;
} }
template<class T>
void SettingsVariable<T>::SetTransform(std::function<T(const T&)> transform)
{
p->transform_ = transform;
}
template<class T> template<class T>
void SettingsVariable<T>::SetValidator(std::function<bool(const T&)> validator) void SettingsVariable<T>::SetValidator(std::function<bool(const T&)> validator)
{ {
@ -384,7 +393,7 @@ bool SettingsVariable<T>::Equals(const SettingsVariableBase& o) const
// This is only ever called with SettingsVariable<T>, so static_cast is safe // This is only ever called with SettingsVariable<T>, so static_cast is safe
const SettingsVariable<T>& v = static_cast<const SettingsVariable<T>&>(o); const SettingsVariable<T>& v = static_cast<const SettingsVariable<T>&>(o);
// Don't compare validator // Don't compare transform or validator
return SettingsVariableBase::Equals(o) && // return SettingsVariableBase::Equals(o) && //
p->value_ == v.p->value_ && // p->value_ == v.p->value_ && //
p->default_ == v.p->default_ && // p->default_ == v.p->default_ && //

View file

@ -165,6 +165,13 @@ public:
*/ */
void SetMaximum(const T& value); void SetMaximum(const T& value);
/**
* Sets a custom transform function for the settings variable.
*
* @param transform Transform function
*/
void SetTransform(std::function<T(const T&)> transform);
/** /**
* Sets a custom validator function for the settings variable. * Sets a custom validator function for the settings variable.
* *

View file

@ -117,6 +117,8 @@ public:
&theme_, &theme_,
&defaultAlertAction_, &defaultAlertAction_,
&clockFormat_, &clockFormat_,
&customStyleDrawLayer_,
&customStyleUrl_,
&defaultTimeZone_, &defaultTimeZone_,
&positioningPlugin_, &positioningPlugin_,
&nmeaBaudRate_, &nmeaBaudRate_,
@ -222,6 +224,8 @@ public:
settings::SettingsInterface<std::string> mapTilerApiKey_ {}; settings::SettingsInterface<std::string> mapTilerApiKey_ {};
settings::SettingsInterface<std::string> defaultAlertAction_ {}; settings::SettingsInterface<std::string> defaultAlertAction_ {};
settings::SettingsInterface<std::string> clockFormat_ {}; settings::SettingsInterface<std::string> clockFormat_ {};
settings::SettingsInterface<std::string> customStyleDrawLayer_ {};
settings::SettingsInterface<std::string> customStyleUrl_ {};
settings::SettingsInterface<std::string> defaultTimeZone_ {}; settings::SettingsInterface<std::string> defaultTimeZone_ {};
settings::SettingsInterface<std::string> positioningPlugin_ {}; settings::SettingsInterface<std::string> positioningPlugin_ {};
settings::SettingsInterface<std::int64_t> nmeaBaudRate_ {}; settings::SettingsInterface<std::int64_t> nmeaBaudRate_ {};
@ -566,6 +570,15 @@ void SettingsDialogImpl::SetupGeneralTab()
mapTilerApiKey_.SetEditWidget(self_->ui->mapTilerApiKeyLineEdit); mapTilerApiKey_.SetEditWidget(self_->ui->mapTilerApiKeyLineEdit);
mapTilerApiKey_.SetResetButton(self_->ui->resetMapTilerApiKeyButton); mapTilerApiKey_.SetResetButton(self_->ui->resetMapTilerApiKeyButton);
customStyleUrl_.SetSettingsVariable(generalSettings.custom_style_url());
customStyleUrl_.SetEditWidget(self_->ui->customMapUrlLineEdit);
customStyleUrl_.SetResetButton(self_->ui->resetCustomMapUrlButton);
customStyleDrawLayer_.SetSettingsVariable(
generalSettings.custom_style_draw_layer());
customStyleDrawLayer_.SetEditWidget(self_->ui->customMapLayerLineEdit);
customStyleDrawLayer_.SetResetButton(self_->ui->resetCustomMapLayerButton);
defaultAlertAction_.SetSettingsVariable( defaultAlertAction_.SetSettingsVariable(
generalSettings.default_alert_action()); generalSettings.default_alert_action());
SCWX_SETTINGS_COMBO_BOX(defaultAlertAction_, SCWX_SETTINGS_COMBO_BOX(defaultAlertAction_,

View file

@ -135,9 +135,9 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>-113</y>
<width>513</width> <width>511</width>
<height>566</height> <height>669</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
@ -482,6 +482,48 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="14" column="2">
<widget class="QLineEdit" name="customMapUrlLineEdit"/>
</item>
<item row="15" column="2">
<widget class="QLineEdit" name="customMapLayerLineEdit"/>
</item>
<item row="14" column="0">
<widget class="QLabel" name="label_26">
<property name="text">
<string>Custom Map URL</string>
</property>
</widget>
</item>
<item row="15" column="0">
<widget class="QLabel" name="label_27">
<property name="text">
<string>Custom Map Layer</string>
</property>
</widget>
</item>
<item row="14" column="4">
<widget class="QToolButton" name="resetCustomMapUrlButton">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../scwx-qt.qrc">
<normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</iconset>
</property>
</widget>
</item>
<item row="15" column="4">
<widget class="QToolButton" name="resetCustomMapLayerButton">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../scwx-qt.qrc">
<normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</iconset>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -568,8 +610,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>63</width> <width>98</width>
<height>18</height> <height>28</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gridLayout_3"> <layout class="QGridLayout" name="gridLayout_3">

@ -1 +1 @@
Subproject commit 6fe42c4f776ced46f0f808109d0d773ffc2255e3 Subproject commit 0ea32947d6a6e39a69d931b2827056e7bc58cbba