7#include "../telemetry/telemetry.hpp"
8#include "../observer/observer.hpp"
9#include "../codec/codec.hpp"
10#include "../dispatch/dispatch.hpp"
12#include "../macros.hpp"
16hi_export_module(hikogui.settings.preferences);
18hi_export
namespace hi::inline
v1 {
35 virtual void reset() noexcept = 0;
49 [[nodiscard]] virtual datum encode() const noexcept = 0;
51 virtual
void decode(datum const& data) = 0;
60 _value_cbt = _value.subscribe(
62 if (
auto tmp = this->encode(); not holds_alternative<std::monostate>(tmp)) {
63 this->_parent.write(_path, this->encode());
65 this->_parent.remove(_path);
68 callback_flags::local);
77 [[nodiscard]] datum encode() const noexcept
override
79 if (*_value != _init) {
82 return datum{std::monostate{}};
86 void decode(datum
const& data)
override
94 callback<void(T)> _value_cbt;
131 preferences() noexcept : _location(), _data(datum::make_map()), _modified(false)
133 using namespace std::chrono_literals;
135 _check_modified_cbt = loop::timer().repeat_function(5s, [
this](
auto...) {
136 this->check_modified();
152 preferences(
std::string const& location) : preferences(
std::filesystem::path{location}) {}
153 preferences(
char const *location) : preferences(
std::filesystem::path{location}) {}
160 preferences(preferences
const&) =
delete;
161 preferences(preferences&&) =
delete;
162 preferences& operator=(preferences
const&) =
delete;
163 preferences& operator=(preferences&&) =
delete;
171 auto const lock = std::scoped_lock(mutex);
181 void save(std::filesystem::path location)
noexcept
183 auto const lock = std::scoped_lock(mutex);
194 auto const lock = std::scoped_lock(mutex);
204 void load(std::filesystem::path location)
noexcept
206 auto const lock = std::scoped_lock(mutex);
215 _data = datum::make_map();
216 for (
auto& item : _items) {
227 void add(std::string_view path, observer<T>
const& item, T init = T{})
noexcept
229 auto item_ = std::make_unique<detail::preference_item<T>>(*
this, path, item,
std::move(init));
237 std::filesystem::path _location;
246 mutable bool _modified =
false;
252 callback<void()> _check_modified_cbt;
254 void _load() noexcept
257 auto file =
hi::file(_location, access_mode::open_for_read);
258 auto text = file.read_string();
259 _data = parse_JSON(text);
261 for (
auto& item : _items) {
265 }
catch (io_error
const& e) {
266 hi_log_warning(
"Could not read preferences file. \"{}\"", e.what());
269 }
catch (parse_error
const& e) {
270 hi_log_error(
"Could not parse preferences file. \"{}\"", e.what());
275 void _save() const noexcept
280 auto tmp_location = _location;
281 tmp_location +=
".tmp";
283 auto file =
hi::file(tmp_location, access_mode::truncate_or_create_for_write | access_mode::rename);
286 file.rename(_location,
true);
288 }
catch (io_error
const& e) {
289 hi_log_error(
"Could not save preferences to file. \"{}\"", e.what());
297 void check_modified() noexcept
299 auto const lock = std::scoped_lock(mutex);
308 void write(jsonpath
const& path, datum
const value)
noexcept
310 auto const lock = std::scoped_lock(mutex);
311 auto *v = _data.find_one_or_create(path);
313 hi_log_fatal(
"Could not write '{}' to preference file '{}'", path, _location.string());
324 datum read(jsonpath
const& path)
noexcept
326 auto const lock = std::scoped_lock(mutex);
327 if (
auto const *
const r = _data.find_one(path)) {
330 return datum{std::monostate{}};
336 void remove(jsonpath
const& path)
noexcept
338 auto const lock = std::scoped_lock(mutex);
339 if (_data.remove(path)) {
344 friend class detail::preference_item_base;
346 friend class detail::preference_item;
349inline void detail::preference_item_base::load() noexcept
351 auto const value = this->_parent.read(_path);
352 if (value.is_undefined()) {
358 hi_log_error(
"Could not decode preference {}, value {}", _path, value);
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
hi_export constexpr std::string format_JSON(datum const &root)
Dump an datum object into a JSON string.
Definition JSON.hpp:330
Encode and decode a type to and from a UTF-8 string.
Definition pickle.hpp:24
T decode(datum rhs) const
Decode a UTF-8 string into a value of a given type.
Definition pickle.hpp:48
datum encode(T const &rhs) const noexcept
Encode the value of a type into a UTF-8 string.
Definition pickle.hpp:30
A File object.
Definition file_intf.hpp:33
Definition preferences.hpp:23
virtual void reset() noexcept=0
Reset the value.
Definition preferences.hpp:55
void reset() noexcept override
Reset the value.
Definition preferences.hpp:71
user preferences.
Definition preferences.hpp:116
void save() const noexcept
Save the preferences.
Definition preferences.hpp:169
void reset() noexcept
Reset data members to their default value.
Definition preferences.hpp:213
preferences(std::filesystem::path location) noexcept
Construct a preferences instance.
Definition preferences.hpp:146
void save(std::filesystem::path location) noexcept
Save the preferences.
Definition preferences.hpp:181
std::mutex mutex
Mutex used to synchronize changes to the preferences.
Definition preferences.hpp:123
preferences() noexcept
Construct a preferences instance.
Definition preferences.hpp:131
void load() noexcept
Load the preferences.
Definition preferences.hpp:192
void load(std::filesystem::path location) noexcept
Load the preferences.
Definition preferences.hpp:204
void add(std::string_view path, observer< T > const &item, T init=T{}) noexcept
Register an observer to a preferences file.
Definition preferences.hpp:227