File indexing completed on 2024-11-24 03:56:28

0001 /*
0002  * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best>
0003  *
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 
0007 #pragma once
0008 
0009 #include <type_traits>
0010 
0011 #include <QWidget>
0012 #include <QLineEdit>
0013 #include <QCheckBox>
0014 #include <QDoubleSpinBox>
0015 #include <QSpinBox>
0016 #include <QComboBox>
0017 #include <QRadioButton>
0018 #include <QPushButton>
0019 
0020 #include "settings.hpp"
0021 
0022 namespace app::settings {
0023 
0024 namespace detail {
0025 
0026 template<class WidgetType, class GetterT, GetterT getter, class SetterT, SetterT setter>
0027 struct WidgetInfoImpl
0028 {
0029     using value_type = decltype((std::declval<WidgetType*>()->*getter)());
0030 
0031     static auto get(const WidgetType* wid)
0032     {
0033         return (wid->*getter)();
0034     }
0035 
0036     template<class Arg>
0037     static void set(WidgetType* wid, Arg&& value)
0038     {
0039         (wid->*setter)(std::forward<Arg>(value));
0040     }
0041 };
0042 
0043 template<class WidgetType>
0044 struct WidgetInfo;
0045 
0046 #define WIDGET_DEF(Class, Getter, Setter) template<> struct WidgetInfo<Class> : public \
0047     WidgetInfoImpl<Class, decltype(&Class::Getter), &Class::Getter, decltype(&Class::Setter), &Class::Setter> {}
0048 
0049 WIDGET_DEF(QSpinBox, value, setValue);
0050 WIDGET_DEF(QDoubleSpinBox, value, setValue);
0051 WIDGET_DEF(QLineEdit, text, setText);
0052 WIDGET_DEF(QCheckBox, isChecked, setChecked);
0053 WIDGET_DEF(QRadioButton, isChecked, setChecked);
0054 WIDGET_DEF(QComboBox, currentIndex, setCurrentIndex);
0055 WIDGET_DEF(QPushButton, isChecked, setChecked);
0056 
0057 #undef WIDGET_DEF
0058 
0059 } // namespace detail
0060 
0061 class WidgetSettingBase
0062 {
0063 public:
0064     virtual ~WidgetSettingBase() {}
0065     virtual void define() = 0;
0066     virtual void load() = 0;
0067     virtual void save() = 0;
0068     virtual void reset() = 0;
0069 };
0070 
0071 /**
0072  * \brief Utility to automatically save/restore widget state using settings
0073  */
0074 template<class WidgetType>
0075 class WidgetSetting : public WidgetSettingBase
0076 {
0077     using Info = detail::WidgetInfo<WidgetType>;
0078     using value_type = typename Info::value_type;
0079 
0080 public:
0081     WidgetSetting(WidgetType* widget, const QString& group, const QString& prefix = {})
0082         : widget(widget), group(group), setting(prefix + widget->objectName())
0083     {}
0084 
0085     /// Defines the setting
0086     void define() override
0087     {
0088         Info::set(widget, settings::define<value_type>(group, setting, Info::get(widget)));
0089     }
0090 
0091     /// Loads the setting and updates the widget
0092     void load() override
0093     {
0094         Info::set(widget, settings::get<value_type>(group, setting, Info::get(widget)));
0095     }
0096 
0097     /// Saves the settings from the widget
0098     void save() override
0099     {
0100         settings::set<value_type>(group, setting, Info::get(widget));
0101     }
0102 
0103     /// Resets the setting to its default
0104     void reset() override
0105     {
0106         Info::set(widget, settings::get_default<value_type>(group, setting));
0107     }
0108 
0109 private:
0110     WidgetType* widget;
0111     QString group;
0112     QString setting;
0113 };
0114 
0115 class WidgetSettingGroup : public WidgetSettingBase
0116 {
0117 public:
0118     template<class WidgetType, class... Args>
0119     void add(WidgetType* widget, Args&&... args)
0120     {
0121         values.push_back(std::make_unique<WidgetSetting<WidgetType>>(widget, std::forward<Args>(args)...));
0122     }
0123 
0124     /// Defines the setting
0125     void define() override
0126     {
0127         for ( auto& setting : values )
0128             setting->define();
0129     }
0130 
0131     /// Loads the setting and updates the widget
0132     void load() override
0133     {
0134         for ( auto& setting : values )
0135             setting->load();
0136     }
0137 
0138     /// Saves the settings from the widget
0139     void save() override
0140     {
0141         for ( auto& setting : values )
0142             setting->save();
0143     }
0144 
0145     /// Resets the setting to its default
0146     void reset() override
0147     {
0148         for ( auto& setting : values )
0149             setting->reset();
0150     }
0151 
0152 private:
0153     std::vector<std::unique_ptr<WidgetSettingBase>> values;
0154 };
0155 
0156 } // namespace app::settings