11#define PDEBUG(...) Ase::debug ("prefs", __VA_ARGS__)
18 value (this,
"value"),
19 metadata (this,
"metadata")
26Property::get_name ()
const
32Property::set_name (
const String &n)
38Property::set_metadata (
const StringS &md)
44PropertyImpl::PropertyImpl (
const Param ¶m,
const PropertyGetter &getter,
45 const PropertySetter &setter,
const PropertyLister &lister) :
46 getter_ (getter), setter_ (setter), lister_ (lister)
52using PrefsValueCallbackList = CallbackList<CString,const Value&>;
61static CStringS notify_preference_queue;
70static bool preferences_autosave =
false;
71static uint timerid_maybe_save_preferences = 0;
74maybe_save_preferences()
76 main_loop->clear_source (&timerid_maybe_save_preferences);
77 if (preferences_autosave && notify_preference_queue.
empty())
78 Preference::save_preferences();
82notify_preference_listeners ()
84 CStringS changed_prefs (notify_preference_queue.
begin(), notify_preference_queue.
end());
85 notify_preference_queue.
clear();
87 std::sort (changed_prefs.begin(), changed_prefs.end());
88 changed_prefs.erase (
std::unique (changed_prefs.begin(), changed_prefs.end()), changed_prefs.end());
90 PrefsMap &prefsmap = prefs_map();
91 for (
auto cident : changed_prefs) {
92 PrefsValue &pv = prefsmap[cident];
93 (*pv.callbacks) (cident, pv.value);
96 const auto callbacklist = prefs_callbacks;
97 (*callbacklist) (changed_prefs);
98 if (preferences_autosave)
99 main_loop->exec_once (577, &timerid_maybe_save_preferences, maybe_save_preferences);
101 main_loop->clear_source (&timerid_maybe_save_preferences);
105queue_notify_preference_listeners (
const CString &cident)
109 const bool need_enqueue = notify_preference_queue.
empty();
110 notify_preference_queue.
push_back (cident);
112 main_loop->exec_now (notify_preference_listeners);
115Preference::Preference (ParameterC parameter)
117 parameter_ = parameter;
118 PrefsMap &prefsmap = prefs_map();
119 auto it = prefsmap.find (parameter_->cident);
121 PrefsValue &pv = it->second;
122 sigh_ = pv.callbacks->add_delcb ([
this] (
const String &ident,
const Value &value) { emit_event (
"notify", ident); });
125Preference::Preference (
const Param ¶m,
const StringValueF &cb)
129 PrefsMap &prefsmap = prefs_map();
130 PrefsValue &pv = prefsmap[parameter_->cident];
132 pv.parameter = parameter_;
133 pv.value = pv.parameter->initial();
134 pv.callbacks = PrefsValueCallbackList::make_shared();
135 sigh_ = pv.callbacks->add_delcb ([
this] (
const String &ident,
const Value &value) { emit_event (
"notify", ident); });
136 queue_notify_preference_listeners (parameter_->cident);
138 Connection connection = on_event (
"notify", [
this,cb] (
const Event &event) { cb (this->parameter_->cident, this->get_value()); });
139 connection_ =
new Connection (connection);
143Preference::~Preference()
146 connection_->disconnect();
148 connection_ =
nullptr;
155Preference::get_value ()
const
158 PrefsValue &pv = prefsmap[parameter_->cident];
163Preference::set_value (
const Value &v)
166 PrefsValue &pv = prefsmap[parameter_->cident];
167 Value next = parameter_->constrain (v);
168 const bool changed = next == pv.value;
169 pv.value = std::move (next);
170 queue_notify_preference_listeners (parameter_->cident);
171 this->value.notify();
176Preference::get (
const String &ident)
178 const CString cident = CString::lookup (ident);
181 auto it = prefsmap.find (cident);
188Preference::find (
const String &ident)
190 const CString cident = CString::lookup (ident);
192 PrefsMap &prefsmap = prefs_map();
193 auto it = prefsmap.find (cident);
195 PrefsValue &pv = it->second;
196 return Preference::make_shared (pv.parameter);
203 for (
const auto &e : prefs_map())
204 strings.push_back (e.first);
205 std::sort (strings.begin(), strings.end());
210Preference::listen (
const std::function<
void(
const CStringS&)> &func)
212 return prefs_callbacks->add_delcb (func);
218 static const String anklangrc = Path::join (Path::config_home(),
"anklang",
"anklangrc.json");
223Preference::load_preferences (
bool autosave)
225 const String jsontext = Path::stringread (pathname_anklangrc());
228 for (ValueField vf : precord) {
229 PreferenceP pref =
find (vf.name);
230 PDEBUG (
"%s: %s %s=%s\n", __func__, pref ?
"loading" :
"ignoring", vf.name, vf.value->repr());
232 pref->set_value (*vf.value);
234 preferences_autosave = autosave;
238Preference::save_preferences ()
241 for (
auto ident : list())
242 precord[ident] = get (ident);
243 const String new_jsontext =
json_stringify (precord, Writ::RELAXED | Writ::SKIP_EMPTYSTRING) +
"\n";
244 const String cur_jsontext = Path::stringread (pathname_anklangrc());
245 if (new_jsontext != cur_jsontext) {
246 PDEBUG (
"%s: %s\n", __func__, precord.repr());
247 Path::stringwrite (pathname_anklangrc(), new_jsontext,
true);
Compact, deduplicating string variant for constant strings.
Reentrant callback list with configurable arguments.
#define assert_return(expr,...)
Return from the current function if expr is unmet and issue an assertion warning.
#define return_unless(cond,...)
Return silently if cond does not evaluate to true with return value ...
The Anklang C++ API namespace.
bool json_parse(const String &jsonstring, T &target)
Parse a well formed JSON string and assign contents to target.
std::string String
Convenience alias for std::string.
uint32_t uint
Provide 'uint' as convenience type.
String json_stringify(const T &source, Writ::Flags flags=Writ::Flags(0))
Create JSON string from source.
Value type used to interface with various property types.