Add QComboBox to SettingsInterface with value mapping

This commit is contained in:
Dan Paulat 2022-12-20 23:27:06 -06:00
parent 70565969dc
commit 602be75222
3 changed files with 130 additions and 10 deletions

View file

@ -4,6 +4,7 @@
#include <scwx/qt/settings/settings_variable.hpp> #include <scwx/qt/settings/settings_variable.hpp>
#include <QAbstractButton> #include <QAbstractButton>
#include <QComboBox>
#include <QCoreApplication> #include <QCoreApplication>
#include <QLineEdit> #include <QLineEdit>
#include <QSpinBox> #include <QSpinBox>
@ -38,6 +39,9 @@ public:
std::unique_ptr<QObject> context_ {std::make_unique<QObject>()}; std::unique_ptr<QObject> context_ {std::make_unique<QObject>()};
QWidget* editWidget_ {nullptr}; QWidget* editWidget_ {nullptr};
QAbstractButton* resetButton_ {nullptr}; QAbstractButton* resetButton_ {nullptr};
std::function<T(const T&)> mapFromValue_ {nullptr};
std::function<T(const T&)> mapToValue_ {nullptr};
}; };
template<class T> template<class T>
@ -80,9 +84,37 @@ void SettingsInterface<T>::SetEditWidget(QWidget* widget)
p->context_.get(), p->context_.get(),
[this](const QString& text) [this](const QString& text)
{ {
// Map to value if required
std::string value {text.toStdString()};
if (p->mapToValue_ != nullptr)
{
value = p->mapToValue_(value);
}
// Attempt to stage the value // Attempt to stage the value
p->stagedValid_ = p->stagedValid_ = p->variable_->StageValue(value);
p->variable_->StageValue(text.toStdString()); p->UpdateResetButton();
});
}
}
else if (QComboBox* comboBox = dynamic_cast<QComboBox*>(widget))
{
if constexpr (std::is_same_v<T, std::string>)
{
QObject::connect(comboBox,
&QComboBox::currentTextChanged,
p->context_.get(),
[this](const QString& text)
{
// Map to value if required
std::string value {text.toStdString()};
if (p->mapToValue_ != nullptr)
{
value = p->mapToValue_(value);
}
// Attempt to stage the value
p->stagedValid_ = p->variable_->StageValue(value);
p->UpdateResetButton(); p->UpdateResetButton();
}); });
} }
@ -175,30 +207,67 @@ void SettingsInterface<T>::SetResetButton(QAbstractButton* button)
p->UpdateResetButton(); p->UpdateResetButton();
} }
template<class T>
void SettingsInterface<T>::SetMapFromValueFunction(
std::function<T(const T&)> function)
{
p->mapFromValue_ = function;
}
template<class T>
void SettingsInterface<T>::SetMapToValueFunction(
std::function<T(const T&)> function)
{
p->mapToValue_ = function;
}
template<class T> template<class T>
void SettingsInterface<T>::Impl::UpdateEditWidget() void SettingsInterface<T>::Impl::UpdateEditWidget()
{ {
// Use the staged value if present, otherwise the current value // Use the staged value if present, otherwise the current value
const std::optional<T> staged = variable_->GetStaged(); const std::optional<T> staged = variable_->GetStaged();
const T value = variable_->GetValue(); const T value = variable_->GetValue();
const T& displayValue = staged.has_value() ? *staged : value; const T& currentValue = staged.has_value() ? *staged : value;
if (QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(editWidget_)) if (QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(editWidget_))
{ {
if constexpr (std::is_integral_v<T>) if constexpr (std::is_integral_v<T>)
{ {
lineEdit->setText(QString::number(displayValue)); lineEdit->setText(QString::number(currentValue));
} }
else if constexpr (std::is_same_v<T, std::string>) else if constexpr (std::is_same_v<T, std::string>)
{ {
lineEdit->setText(QString::fromStdString(displayValue)); if (mapFromValue_ != nullptr)
{
lineEdit->setText(
QString::fromStdString(mapFromValue_(currentValue)));
}
else
{
lineEdit->setText(QString::fromStdString(currentValue));
}
}
}
else if (QComboBox* comboBox = dynamic_cast<QComboBox*>(editWidget_))
{
if constexpr (std::is_same_v<T, std::string>)
{
if (mapFromValue_ != nullptr)
{
comboBox->setCurrentText(
QString::fromStdString(mapFromValue_(currentValue)));
}
else
{
comboBox->setCurrentText(QString::fromStdString(currentValue));
}
} }
} }
else if (QSpinBox* spinBox = dynamic_cast<QSpinBox*>(editWidget_)) else if (QSpinBox* spinBox = dynamic_cast<QSpinBox*>(editWidget_))
{ {
if constexpr (std::is_integral_v<T>) if constexpr (std::is_integral_v<T>)
{ {
spinBox->setValue(static_cast<int>(displayValue)); spinBox->setValue(static_cast<int>(currentValue));
} }
} }
} }

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <functional>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
@ -52,6 +53,24 @@ public:
*/ */
void SetResetButton(QAbstractButton* button); void SetResetButton(QAbstractButton* button);
/**
* If the edit widget displays a different value than what is stored in the
* settings variable, a mapping function must be provided in order to convert
* the value used by the edit widget from the settings value.
*
* @param function Map from settings value function
*/
void SetMapFromValueFunction(std::function<T(const T&)> function);
/**
* If the edit widget displays a different value than what is stored in the
* settings variable, a mapping function must be provided in order to convert
* the value used by the edit widget to the settings value.
*
* @param function Map to settings value function
*/
void SetMapToValueFunction(std::function<T(const T&)> function);
private: private:
class Impl; class Impl;
std::unique_ptr<Impl> p; std::unique_ptr<Impl> p;

View file

@ -6,6 +6,8 @@
#include <scwx/qt/manager/settings_manager.hpp> #include <scwx/qt/manager/settings_manager.hpp>
#include <scwx/qt/settings/settings_interface.hpp> #include <scwx/qt/settings/settings_interface.hpp>
#include <format>
#include <QToolButton> #include <QToolButton>
namespace scwx namespace scwx
@ -101,10 +103,8 @@ void SettingsDialogImpl::SetupGeneralTab()
// Add sorted radar sites // Add sorted radar sites
for (std::shared_ptr<config::RadarSite>& radarSite : radarSites) for (std::shared_ptr<config::RadarSite>& radarSite : radarSites)
{ {
QString text = QString text = QString::fromStdString(
QString("%1 (%2)") std::format("{} ({})", radarSite->id(), radarSite->location_name()));
.arg(QString::fromStdString(radarSite->id()))
.arg(QString::fromStdString(radarSite->location_name()));
self_->ui->radarSiteComboBox->addItem(text); self_->ui->radarSiteComboBox->addItem(text);
} }
@ -112,6 +112,38 @@ void SettingsDialogImpl::SetupGeneralTab()
manager::SettingsManager::general_settings(); manager::SettingsManager::general_settings();
defaultRadarSite_.SetSettingsVariable(generalSettings.default_radar_site()); defaultRadarSite_.SetSettingsVariable(generalSettings.default_radar_site());
defaultRadarSite_.SetMapFromValueFunction(
[](const std::string& id) -> std::string
{
// Get the radar site associated with the ID
std::shared_ptr<config::RadarSite> radarSite =
config::RadarSite::Get(id);
if (radarSite == nullptr)
{
// No radar site found, just return the ID
return id;
}
// Add location details to the radar site
return std::format(
"{} ({})", radarSite->id(), radarSite->location_name());
});
defaultRadarSite_.SetMapToValueFunction(
[](const std::string& text) -> std::string
{
// Find the position of location details
size_t pos = text.rfind(" (");
if (pos == std::string::npos)
{
// No location details found, just return the text
return text;
}
// Remove location details from the radar site
return text.substr(0, pos);
});
defaultRadarSite_.SetEditWidget(self_->ui->radarSiteComboBox); defaultRadarSite_.SetEditWidget(self_->ui->radarSiteComboBox);
defaultRadarSite_.SetResetButton(self_->ui->resetRadarSiteButton); defaultRadarSite_.SetResetButton(self_->ui->resetRadarSiteButton);