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