11#define PDEBUG(...) Ase::debug ("prefs", __VA_ARGS__)
23Property::name ()
const
29Property::name (
const String &n)
35Property::metadata (
const StringS &md)
41PropertyImpl::PropertyImpl (
const Param ¶m,
const PropertyGetter &getter,
43 getter_ (getter), setter_ (setter), lister_ (lister)
49using PrefsValueCallbackList = CallbackList<CString,const Value&>;
58static CStringS notify_preference_queue;
67static bool preferences_autosave =
false;
68static LoopID timerid_maybe_save_preferences = LoopID::INVALID;
71maybe_save_preferences()
73 main_loop->cancel (&timerid_maybe_save_preferences);
74 if (preferences_autosave && notify_preference_queue.
empty())
75 Preference::save_preferences();
79notify_preference_listeners ()
81 CStringS changed_prefs (notify_preference_queue.
begin(), notify_preference_queue.
end());
82 notify_preference_queue.
clear();
84 std::sort (changed_prefs.begin(), changed_prefs.end());
85 changed_prefs.erase (
std::unique (changed_prefs.begin(), changed_prefs.end()), changed_prefs.end());
87 PrefsMap &prefsmap = prefs_map();
88 for (
auto cident : changed_prefs) {
89 PrefsValue &pv = prefsmap[cident];
90 (*pv.callbacks) (cident, pv.value);
93 const auto callbacklist = prefs_callbacks;
94 (*callbacklist) (changed_prefs);
95 if (preferences_autosave)
96 main_loop->exec_once (577, &timerid_maybe_save_preferences, maybe_save_preferences);
98 main_loop->cancel (&timerid_maybe_save_preferences);
102queue_notify_preference_listeners (
const CString &cident)
106 const bool need_enqueue = notify_preference_queue.
empty();
107 notify_preference_queue.
push_back (cident);
109 main_loop->add (notify_preference_listeners, LoopPriority::NOTIFY);
112Preference::Preference (ParameterC parameter)
114 parameter_ = parameter;
115 PrefsMap &prefsmap = prefs_map();
116 auto it = prefsmap.find (parameter_->cident);
118 PrefsValue &pv = it->second;
119 sigh_ = pv.callbacks->add_delcb ([
this] (
const String &ident,
const Value &value) { emit_event (
"notify", ident); });
122Preference::Preference (
const Param ¶m,
const StringValueF &cb)
126 PrefsMap &prefsmap = prefs_map();
127 PrefsValue &pv = prefsmap[parameter_->cident];
129 pv.parameter = parameter_;
130 pv.value = pv.parameter->initial();
131 pv.callbacks = PrefsValueCallbackList::make_shared();
132 sigh_ = pv.callbacks->add_delcb ([
this] (
const String &ident,
const Value &value) { emit_event (
"notify", ident); });
133 queue_notify_preference_listeners (parameter_->cident);
135 Connection connection = on_event (
"notify", [
this,cb] (
const Event &event) { cb (this->parameter_->cident, this->value()); });
136 connection_ =
new Connection (connection);
140Preference::~Preference()
143 connection_->disconnect();
145 connection_ =
nullptr;
152Preference::value ()
const
155 PrefsValue &pv = prefsmap[parameter_->cident];
163 PrefsValue &pv = prefsmap[parameter_->cident];
164 Value next = parameter_->constrain (v);
165 const bool changed = next == pv.value;
166 pv.value = std::move (next);
167 queue_notify_preference_listeners (parameter_->cident);
168 emit_notify (
"value");
173Preference::get (
const String &ident)
175 const CString cident = CString::lookup (ident);
178 auto it = prefsmap.find (cident);
185Preference::find (
const String &ident)
187 const CString cident = CString::lookup (ident);
189 PrefsMap &prefsmap = prefs_map();
190 auto it = prefsmap.find (cident);
192 PrefsValue &pv = it->second;
193 return Preference::make_shared (pv.parameter);
200 for (
const auto &e : prefs_map())
201 strings.push_back (e.first);
202 std::sort (strings.begin(), strings.end());
207Preference::listen (
const std::function<
void(
const CStringS&)> &func)
209 return prefs_callbacks->add_delcb (func);
215 static const String anklangrc = Path::join (Path::config_home(),
"anklang",
"anklangrc.json");
220Preference::load_preferences (
bool autosave)
222 const String jsontext = Path::stringread (pathname_anklangrc());
225 for (ValueField vf : precord) {
226 PreferenceP pref =
find (vf.name);
227 PDEBUG (
"%s: %s %s=%s\n", __func__, pref ?
"loading" :
"ignoring", vf.name, vf.value->repr());
229 pref->value (*vf.value);
231 preferences_autosave = autosave;
235Preference::save_preferences ()
238 for (
auto ident : list())
239 precord[ident] = get (ident);
240 const String new_jsontext =
json_stringify (precord, Writ::RELAXED | Writ::SKIP_EMPTYSTRING) +
"\n";
241 const String cur_jsontext = Path::stringread (pathname_anklangrc());
242 if (new_jsontext != cur_jsontext) {
243 PDEBUG (
"%s: %s\n", __func__, precord.repr());
244 Path::stringwrite (pathname_anklangrc(), new_jsontext,
true);
Compact, deduplicating string variant for constant strings.
Reentrant callback list with configurable arguments.
virtual String ident() const =0
Unique name (per owner) of this Property.
#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::vector< String > StringS
Convenience alias for a std::vector<std::string>.
std::function< ChoiceS(const ParameterProperty &)> PropertyLister
Function type to list Choice Property values.
std::string String
Convenience alias for std::string.
std::function< void(Value &)> PropertyGetter
Function type for Property value getters.
std::function< bool(const Value &)> PropertySetter
Function type for Property value setters.
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.